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 parent 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 parent 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
104 package My::Child;
105
106 use strict;
107 use parent qw( My::Parent );
108
109 sub brush_teeth {
110 my ( $self ) = @_;
111 $self->_wet_toothbrush();
112 }
113
114 sub wash_face { return }
115
116 # Create a class-based observer
117
118 package My::ParentRules;
119
120 sub update {
121 my ( $item, $action ) = @_;
122 if ( $action eq 'prepare_for_bed' ) {
123 $item->brush_teeth;
124 $item->wash_face;
125 }
126 }
127
128 My::Parent->add_observer( __PACKAGE__ );
129
130 $parent->prepare_for_bed # brush, floss, gargle, and wash face
131 $child->prepare_for_bed # pretend to brush, pretend to wash face
132
134 If you have ever used Java, you may have run across the
135 "java.util.Observable" class and the "java.util.Observer" interface.
136 With them you can decouple an object from the one or more objects that
137 wish to be notified whenever particular events occur.
138
139 These events occur based on a contract with the observed item. They may
140 occur at the beginning, in the middle or end of a method. In addition,
141 the object knows that it is being observed. It just does not know how
142 many or what types of objects are doing the observing. It can therefore
143 control when the messages get sent to the obsevers.
144
145 The behavior of the observers is up to you. However, be aware that we
146 do not do any error handling from calls to the observers. If an
147 observer throws a "die", it will bubble up to the observed item and
148 require handling there. So be careful.
149
151 Throughout this documentation we refer to an 'observed item' or
152 'observable item'. This ambiguity refers to the fact that both a class
153 and an object can be observed. The behavior when notifying observers is
154 identical. The only difference comes in which observers are notified.
155 (See "Observable Classes and Objects" for more information.)
156
157 Observable Classes and Objects
158 The observable item does not need to implement any extra methods or
159 variables. Whenever it wants to let observers know about a state-change
160 or occurrence in the object, it just needs to call 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 parent qw( Class::Observable );
183 sub new { return bless( {}, $_[0] ) }
184 sub yodel { $_[0]->notify_observers }
185
186 package Baz;
187 use parent 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
235 specific object ("observer_c" coderef) as well as from its class (Baz)
236 and the parent (Foo) of its class.
237
238 Observers
239 There are three types of observers: classes, objects, and subroutines.
240 All three respond to events when notify_observers() is called from an
241 observable item. The differences among the three are are:
242
243 • A class or object observer must implement a method update() which
244 is called when a state-change occurs. The name of the subroutine
245 observer is irrelevant.
246
247 • A class or object observer must take at least two arguments: itself
248 and the observed item. The subroutine observer is obligated to take
249 only one argument, the observed item.
250
251 Both types of observers may also take an action name and a hashref
252 of parameters as optional arguments. Whether these are used depends
253 on the observed item.
254
255 • Object observers can maintain state between responding to
256 observations.
257
258 Examples:
259
260 Subroutine observer:
261
262 sub respond {
263 my ( $item, $action, $params ) = @_;
264 return unless ( $action eq 'update' );
265 # ...
266 }
267 $observable->add_observer( \&respond );
268
269 Class observer:
270
271 package My::ObserverC;
272
273 sub update {
274 my ( $class, $item, $action, $params ) = @_;
275 return unless ( $action eq 'update' );
276 # ...
277 }
278
279 Object observer:
280
281 package My::ObserverO;
282
283 sub new {
284 my ( $class, $type ) = @_;
285 return bless ( { type => $type }, $class );
286 }
287
288 sub update {
289 my ( $self, $item, $action, $params ) = @_;
290 return unless ( $action eq $self->{type} );
291 # ...
292 }
293
294 Observable Objects and DESTROY
295 This class has a "DESTROY" method which must run when an instance of an
296 observable class goes out of scope in order to clean up the observers
297 added to that instance.
298
299 If there is no other destructor in the inheritance tree, this will end
300 up happening naturally and everything will be fine.
301
302 If it does not get called, then the list of observers will leak (which
303 also prevents the observers in it from being garbage-collected) and may
304 become associated with a different instance created later at the same
305 memory address as a previous instance.
306
307 This may happen if a class needs its own "DESTROY" method when it also
308 wants to inherit from Class::Observer (even indirectly!), because perl
309 only invokes the single nearest inherited "DESTROY".
310
311 The most straightforward (but maybe not best) way to ensure that the
312 destructor is called is to do something like this:
313
314 # in My::Class
315 sub DESTROY {
316 # ...
317 $self->Class::Observable::DESTROY;
318 # ...
319 }
320
321 A better way may be to to write all destructors in your class hierarchy
322 with the expectation that all of them will be called (which would
323 usually be preferred anyway) and then enforcing that expectation by
324 writing all of them as follows:
325
326 use mro;
327 sub DESTROY {
328 # ...
329 $self->maybe::next::method;
330 # ...
331 }
332
333 (Perl being Perl, of course, there are many other ways to go about
334 this.)
335
337 notify_observers( [ $action, @params ] )
338
339 Called from the observed item, this method sends a message to all
340 observers that a state-change has occurred. The observed item can
341 optionally include additional information about the type of change that
342 has occurred and any additional parameters @params which get passed
343 along to each observer. The observed item should indicate in its API
344 what information will be passed along to the observers in $action and
345 @params.
346
347 Returns: Nothing
348
349 Example:
350
351 sub remove {
352 my ( $self ) = @_;
353 eval { $self->_remove_item_from_datastore };
354 if ( $@ ) {
355 $self->notify_observers( 'remove-fail', error_message => $@ );
356 } else {
357 $self->notify_observers( 'remove' );
358 }
359 }
360
361 add_observer( @observers )
362
363 Adds the one or more observers (@observer) to the observed item. Each
364 observer can be a class name, object or subroutine -- see "Types of
365 Observers".
366
367 Returns: The number of observers now observing the item.
368
369 Example:
370
371 # Add a salary check (as a subroutine observer) for a particular
372 # person
373 my $person = Person->fetch( 3843857 );
374 $person->add_observer( \&salary_check );
375
376 # Add a salary check (as a class observer) for all people
377 Person->add_observer( 'Validate::Salary' );
378
379 # Add a salary check (as an object observer) for all people
380 my $salary_policy = Company::Policy::Salary->new( 'pretax' );
381 Person->add_observer( $salary_policy );
382
383 delete_observer( @observers )
384
385 Removes the one or more observers (@observer) from the observed item.
386 Each observer can be a class name, object or subroutine -- see "Types
387 of Observers".
388
389 Note that this only deletes each observer from the observed item
390 itself. It does not remove observer from any parent classes. Therefore,
391 if an observer is not registered directly with the observed item
392 nothing will be removed.
393
394 Returns: The number of observers now observing the item.
395
396 Examples:
397
398 # Remove a class observer from an object
399 $person->delete_observer( 'Lech::Ogler' );
400
401 # Remove an object observer from a class
402 Person->delete_observer( $salary_policy );
403
404 delete_all_observers()
405
406 Removes all observers from the observed item.
407
408 Note that this only deletes observers registered directly with the
409 observed item. It does not clear out observers from any parent classes.
410
411 WARNING: This method was renamed from "delete_observers". The
412 "delete_observers" call still works but is deprecated and will
413 eventually be removed.
414
415 Returns: The number of observers removed.
416
417 Example:
418
419 Person->delete_all_observers();
420
421 get_observers()
422
423 Returns all observers for an observed item, as well as the observers
424 for its class and parents as applicable. See "Observable Classes and
425 Objects" for more information.
426
427 Returns: list of observers.
428
429 Example:
430
431 my @observers = Person->get_observers;
432 foreach my $o ( @observers ) {
433 print "Observer is a: ";
434 print "Class" unless ( ref $o );
435 print "Subroutine" if ( ref $o eq 'CODE' );
436 print "Object" if ( ref $o and ref $o ne 'CODE' );
437 print "\n";
438 }
439
440 copy_observers( $copy_to_observable )
441
442 Copies all observers from one observed item to another. We get all
443 observers from the source, including the observers of parents. (Behind
444 the scenes we just use get_observers(), so read that for what we copy.)
445
446 We make no effort to ensure we don't copy an observer that's already
447 watching the object we're copying to. If this happens you will appear
448 to get duplicate observations. (But it shouldn't happen often, if
449 ever.)
450
451 Returns: number of observers copied
452
453 Example:
454
455 # Copy all observers of the 'Person' class to also observe the
456 # 'Address' class
457
458 Person->copy_observers( Address );
459
460 # Copy all observers of a $person to also observe a particular
461 # $address
462
463 $person->copy_observers( $address )
464
465 count_observers()
466
467 Counts the number of observers for an observed item, including ones
468 inherited from its class and/or parent classes. See "Observable Classes
469 and Objects" for more information.
470
472 APIs for "java.util.Observable" and "java.util.Observer". (Docs below
473 are included with JDK 1.4 but have been consistent for some time.)
474
475 <http://java.sun.com/j2se/1.4/docs/api/java/util/Observable.html>
476
477 <http://java.sun.com/j2se/1.4/docs/api/java/util/Observer.html>
478
479 "Observer and Observable", Todd Sundsted,
480 <http://www.javaworld.com/javaworld/jw-10-1996/jw-10-howto_p.html>
481
482 "Java Tip 29: How to decouple the Observer/Observable object model",
483 Albert Lopez, <http://www.javaworld.com/javatips/jw-javatip29_p.html>
484
486 Class::ISA
487
488 Class::Trigger
489
490 Aspect
491
493 Aristotle Pagaltzis <pagaltzis@gmx.de>
494
495 Chris Winters
496
498 This documentation is copyright (c) 2002-2004 Chris Winters.
499
500 This software is copyright (c) 2021 by Aristotle Pagaltzis.
501
502 This is free software; you can redistribute it and/or modify it under
503 the same terms as the Perl 5 programming language system itself.
504
505
506
507perl v5.36.0 2023-01-20 Class::Observable(3)