1Class::Observable(3) User Contributed Perl Documentation Class::Observable(3)
2
3
4
6 Class::Observable - Allow other classes and objects to respond to
7 events in yours
8
10 # Define an observable class
11
12 package My::Object;
13
14 use base qw( Class::Observable );
15
16 # Tell all classes/objects observing this object that a state-change
17 # has occurred
18
19 sub create {
20 my ( $self ) = @_;
21 eval { $self->_perform_create() };
22 if ( $@ ) {
23 My::Exception->throw( "Error saving: $@" );
24 }
25 $self->notify_observers();
26 }
27
28 # Same thing, except make the type of change explicit and pass
29 # arguments.
30
31 sub edit {
32 my ( $self ) = @_;
33 my %old_values = $self->extract_values;
34 eval { $self->_perform_edit() };
35 if ( $@ ) {
36 My::Exception->throw( "Error saving: $@" );
37 }
38 $self->notify_observers( 'edit', old_values => \%old_values );
39 }
40
41 # Define an observer
42
43 package My::Observer;
44
45 sub update {
46 my ( $class, $object, $action ) = @_;
47 unless ( $action ) {
48 warn "Cannot operation on [", $object->id, "] without action";
49 return;
50 }
51 $class->_on_save( $object ) if ( $action eq 'save' );
52 $class->_on_update( $object ) if ( $action eq 'update' );
53 }
54
55 # Register the observer class with all instances of the observable
56 # class
57
58 My::Object->add_observer( 'My::Observer' );
59
60 # Register the observer class with a single instance of the
61 # observable class
62
63 my $object = My::Object->new( 'foo' );
64 $object->add_observer( 'My::Observer' );
65
66 # Register an observer object the same way
67
68 my $observer = My::Observer->new( 'bar' );
69 My::Object->add_observer( $observer );
70 my $object = My::Object->new( 'foo' );
71 $object->add_observer( $observer );
72
73 # Register an observer using a subroutine
74
75 sub catch_observation { ... }
76
77 My::Object->add_observer( \&catch_observation );
78 my $object = My::Object->new( 'foo' );
79 $object->add_observer( \&catch_observation );
80
81 # Define the observable class as a parent and allow the observers to
82 # be used by the child
83
84 package My::Parent;
85
86 use strict;
87 use base qw( Class::Observable );
88
89 sub prepare_for_bed {
90 my ( $self ) = @_;
91 $self->notify_observers( 'prepare_for_bed' );
92 }
93
94 sub brush_teeth {
95 my ( $self ) = @_;
96 $self->_brush_teeth( time => 45 );
97 $self->_floss_teeth( time => 30 );
98 $self->_gargle( time => 30 );
99 }
100
101 sub wash_face { ... }
102
103 package My::Child;
104
105 use strict;
106 use base qw( My::Parent );
107
108 sub brush_teeth {
109 my ( $self ) = @_;
110 $self->_wet_toothbrush();
111 }
112
113 sub wash_face { return }
114
115 # Create a class-based observer
116
117 package My::ParentRules;
118
119 sub update {
120 my ( $item, $action ) = @_;
121 if ( $action eq 'prepare_for_bed' ) {
122 $item->brush_teeth;
123 $item->wash_face;
124 }
125 }
126
127 My::Parent->add_observer( __PACKAGE__ );
128
129 $parent->prepare_for_bed # brush, floss, gargle, and wash face
130 $child->prepare_for_bed # pretend to brush, pretend to wash face
131
133 If you have ever used Java, you may have run across the
134 "java.util.Observable" class and the "java.util.Observer" interface.
135 With them you can decouple an object from the one or more objects that
136 wish to be notified whenever particular events occur.
137
138 These events occur based on a contract with the observed item. They may
139 occur at the beginning, in the middle or end of a method. In addition,
140 the object knows that it is being observed. It just does not know how
141 many or what types of objects are doing the observing. It can therefore
142 control when the messages get sent to the obsevers.
143
144 The behavior of the observers is up to you. However, be aware that we
145 do not do any error handling from calls to the observers. If an
146 observer throws a "die", it will bubble up to the observed item and
147 require handling there. So be careful.
148
149 Throughout this documentation we refer to an 'observed item' or
150 'observable item'. This ambiguity refers to the fact that both a class
151 and an object can be observed. The behavior when notifying observers is
152 identical. The only difference comes in which observers are notified.
153 (See "Observable Classes and Objects" for more information.)
154
155 Observable Classes and Objects
156
157 The observable item does not need to implement any extra methods or
158 variables. Whenever it wants to let observers know about a state-change
159 or occurrence in the object, it just needs to call
160 "notify_observers()".
161
162 As noted above, whether the observed item is a class or object does not
163 matter -- the behavior is the same. The difference comes in determining
164 which observers are to be notified:
165
166 · If the observed item is a class, all objects instantiated from that
167 class will use these observers. In addition, all subclasses and
168 objects instantiated from the subclasses will use these observers.
169
170 · If the observed item is an object, only that particular object will
171 use its observers. Once it falls out of scope then the observers
172 will no longer be available. (See "Observable Objects and DESTROY"
173 below.)
174
175 Whichever you chose, your documentation should make clear which type of
176 observed item observers can expect.
177
178 So given the following example:
179
180 BEGIN {
181 package Foo;
182 use base qw( Class::Observable );
183 sub new { return bless( {}, $_[0] ) }
184 sub yodel { $_[0]->notify_observers }
185
186 package Baz;
187 use base qw( Foo );
188 sub yell { $_[0]->notify_observers }
189 }
190
191 sub observer_a { print "Observation A from [$_[0]]\n" }
192 sub observer_b { print "Observation B from [$_[0]]\n" }
193 sub observer_c { print "Observation C from [$_[0]]\n" }
194
195 Foo->add_observer( \&observer_a );
196 Baz->add_observer( \&observer_b );
197
198 my $foo = Foo->new;
199 print "Yodeling...\n";
200 $foo->yodel;
201
202 my $baz_a = Baz->new;
203 print "Yelling A...\n";
204 $baz_a->yell;
205
206 my $baz_b = Baz->new;
207 $baz_b->add_observer( \&observer_c );
208 print "Yelling B...\n";
209 $baz_b->yell;
210
211 You would see something like
212
213 Yodeling...
214 Observation A from [Foo=HASH(0x80f7acc)]
215 Yelling A...
216 Observation B from [Baz=HASH(0x815c2b4)]
217 Observation A from [Baz=HASH(0x815c2b4)]
218 Yelling B...
219 Observation C from [Baz=HASH(0x815c344)]
220 Observation B from [Baz=HASH(0x815c344)]
221 Observation A from [Baz=HASH(0x815c344)]
222
223 And since "Bar" is a child of "Foo" and each has one class-level
224 observer, running either:
225
226 my @observers = Baz->get_observers();
227 my @observers = $baz_a->get_observers();
228
229 would return a two-item list. The first item would be the "observer_b"
230 code reference, the second the "observer_a" code reference. Running:
231
232 my @observers = $baz_b->get_observers();
233
234 would return a three-item list, including the observer for that spe‐
235 cific object ("observer_c" coderef) as well as from its class (Baz) and
236 the parent (Foo) of its class.
237
238 Observers
239
240 There are three types of observers: classes, objects, and subroutines.
241 All three respond to events when "notify_observers()" is called from an
242 observable item. The differences among the three are are:
243
244 · A class or object observer must implement a method "update()" which
245 is called when a state-change occurs. The name of the subroutine
246 observer is irrelevant.
247
248 · A class or object observer must take at least two arguments: itself
249 and the observed item. The subroutine observer is obligated to take
250 only one argument, the observed item.
251
252 Both types of observers may also take an action name and a hashref
253 of parameters as optional arguments. Whether these are used depends
254 on the observed item.
255
256 · Object observers can maintain state between responding to observa‐
257 tions.
258
259 Examples:
260
261 Subroutine observer:
262
263 sub respond {
264 my ( $item, $action, $params ) = @_;
265 return unless ( $action eq 'update' );
266 # ...
267 }
268 $observable->add_observer( \&respond );
269
270 Class observer:
271
272 package My::ObserverC;
273
274 sub update {
275 my ( $class, $item, $action, $params ) = @_;
276 return unless ( $action eq 'update' );
277 # ...
278 }
279
280 Object observer:
281
282 package My::ObserverO;
283
284 sub new {
285 my ( $class, $type ) = @_;
286 return bless ( { type => $type }, $class );
287 }
288
289 sub update {
290 my ( $self, $item, $action, $params ) = @_;
291 return unless ( $action eq $self->{type} );
292 # ...
293 }
294
295 Observable Objects and DESTROY
296
297 Previous versions of this module had a problem with maintaining refer‐
298 ences to observable objects/coderefs. As a result they'd never be
299 destroyed. As of 1.04 we're using weak references with "weaken" in
300 Scalar::Util so this shouldn't be a problem any longer.
301
303 Observed Item Methods
304
305 notify_observers( [ $action, @params ] )
306
307 Called from the observed item, this method sends a message to all
308 observers that a state-change has occurred. The observed item can
309 optionally include additional information about the type of change that
310 has occurred and any additional parameters @params which get passed
311 along to each observer. The observed item should indicate in its API
312 what information will be passed along to the observers in $action and
313 @params.
314
315 Returns: Nothing
316
317 Example:
318
319 sub remove {
320 my ( $self ) = @_;
321 eval { $self->_remove_item_from_datastore };
322 if ( $@ ) {
323 $self->notify_observers( 'remove-fail', error_message => $@ );
324 }
325 else {
326 $self->notify_observers( 'remove' );
327 }
328 }
329
330 add_observer( @observers )
331
332 Adds the one or more observers (@observer) to the observed item. Each
333 observer can be a class name, object or subroutine -- see "Types of
334 Observers".
335
336 Returns: The number of observers now observing the item.
337
338 Example:
339
340 # Add a salary check (as a subroutine observer) for a particular
341 # person
342 my $person = Person->fetch( 3843857 );
343 $person->add_observer( \&salary_check );
344
345 # Add a salary check (as a class observer) for all people
346 Person->add_observer( 'Validate::Salary' );
347
348 # Add a salary check (as an object observer) for all people
349 my $salary_policy = Company::Policy::Salary->new( 'pretax' );
350 Person->add_observer( $salary_policy );
351
352 delete_observer( @observers )
353
354 Removes the one or more observers (@observer) from the observed item.
355 Each observer can be a class name, object or subroutine -- see "Types
356 of Observers".
357
358 Note that this only deletes each observer from the observed item
359 itself. It does not remove observer from any parent classes. Therefore,
360 if an observer is not registered directly with the observed item noth‐
361 ing will be removed.
362
363 Returns: The number of observers now observing the item.
364
365 Examples:
366
367 # Remove a class observer from an object
368 $person->delete_observer( 'Lech::Ogler' );
369
370 # Remove an object observer from a class
371 Person->delete_observer( $salary_policy );
372
373 delete_all_observers()
374
375 Removes all observers from the observed item.
376
377 Note that this only deletes observers registered directly with the
378 observed item. It does not clear out observers from any parent classes.
379
380 WARNING: This method was renamed from "delete_observers". The
381 "delete_observers" call still works but is deprecated and will eventu‐
382 ally be removed.
383
384 Returns: The number of observers removed.
385
386 Example:
387
388 Person->delete_all_observers();
389
390 get_observers()
391
392 Returns all observers for an observed item, as well as the observers
393 for its class and parents as applicable. See "Observable Classes and
394 Objects" for more information.
395
396 Returns: list of observers.
397
398 Example:
399
400 my @observers = Person->get_observers;
401 foreach my $o ( @observers ) {
402 print "Observer is a: ";
403 print "Class" unless ( ref $o );
404 print "Subroutine" if ( ref $o eq 'CODE' );
405 print "Object" if ( ref $o and ref $o ne 'CODE' );
406 print "\n";
407 }
408
409 copy_observers( $copy_to_observable )
410
411 Copies all observers from one observed item to another. We get all
412 observers from the source, including the observers of parents. (Behind
413 the scenes we just use "get_observers()", so read that for what we
414 copy.)
415
416 We make no effort to ensure we don't copy an observer that's already
417 watching the object we're copying to. If this happens you will appear
418 to get duplicate observations. (But it shouldn't happen often, if
419 ever.)
420
421 Returns: number of observers copied
422
423 Example:
424
425 # Copy all observers of the 'Person' class to also observe the
426 # 'Address' class
427
428 Person->copy_observers( Address );
429
430 # Copy all observers of a $person to also observe a particular
431 # $address
432
433 $person->copy_observers( $address )
434
435 count_observers()
436
437 Counts the number of observers for an observed item, including ones
438 inherited from its class and/or parent classes. See "Observable Classes
439 and Objects" for more information.
440
441 Debugging Methods
442
443 Note that the debugging messages will try to get information about the
444 observed item if called from an object. If you have an "id()" method in
445 the object its value will be used in the message, otherwise it will be
446 described as "an instance of class Foo".
447
448 SET_DEBUG( $bool )
449
450 Turn debugging on or off. If set the built-in implementation of
451 "observer_log()" will issue a warn at appropriate times during the
452 process.
453
454 observer_log( @message )
455
456 Issues a "warn" if "SET_DEBUG" hsa been called with a true value. This
457 gets called multiple times during the registration and notification
458 process.
459
460 To catch the "warn" calls just override this method.
461
462 observer_error( @message )
463
464 Issues a "die" if we catch an exception when notifying observers. To
465 catch the "die" and do something else with it just override this
466 method.
467
469 APIs for "java.util.Observable" and "java.util.Observer". (Docs below
470 are included with JDK 1.4 but have been consistent for some time.)
471
472 <http://java.sun.com/j2se/1.4/docs/api/java/util/Observable.html>
473
474 <http://java.sun.com/j2se/1.4/docs/api/java/util/Observer.html>
475
476 "Observer and Observable", Todd Sundsted, <http://www.java‐
477 world.com/javaworld/jw-10-1996/jw-10-howto_p.html>
478
479 "Java Tip 29: How to decouple the Observer/Observable object model",
480 Albert Lopez, <http://www.javaworld.com/javatips/jw-javatip29_p.html>
481
483 Class::ISA
484
485 Class::Trigger
486
487 Aspect
488
490 Copyright (c) 2002-2004 Chris Winters. All rights reserved.
491
492 This library is free software; you can redistribute it and/or modify it
493 under the same terms as Perl itself.
494
496 Chris Winters <chris@cwinters.com>
497
498
499
500perl v5.8.8 2004-10-16 Class::Observable(3)