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
161 "notify_observers()".
162
163 As noted above, whether the observed item is a class or object does not
164 matter -- the behavior is the same. The difference comes in determining
165 which observers are to be notified:
166
167 • If the observed item is a class, all objects instantiated from that
168 class will use these observers. In addition, all subclasses and
169 objects instantiated from the subclasses will use these observers.
170
171 • If the observed item is an object, only that particular object will
172 use its observers. Once it falls out of scope then the observers
173 will no longer be available. (See "Observable Objects and DESTROY"
174 below.)
175
176 Whichever you chose, your documentation should make clear which type of
177 observed item observers can expect.
178
179 So given the following example:
180
181 BEGIN {
182 package Foo;
183 use parent qw( Class::Observable );
184 sub new { return bless( {}, $_[0] ) }
185 sub yodel { $_[0]->notify_observers }
186
187 package Baz;
188 use parent qw( Foo );
189 sub yell { $_[0]->notify_observers }
190 }
191
192 sub observer_a { print "Observation A from [$_[0]]\n" }
193 sub observer_b { print "Observation B from [$_[0]]\n" }
194 sub observer_c { print "Observation C from [$_[0]]\n" }
195
196 Foo->add_observer( \&observer_a );
197 Baz->add_observer( \&observer_b );
198
199 my $foo = Foo->new;
200 print "Yodeling...\n";
201 $foo->yodel;
202
203 my $baz_a = Baz->new;
204 print "Yelling A...\n";
205 $baz_a->yell;
206
207 my $baz_b = Baz->new;
208 $baz_b->add_observer( \&observer_c );
209 print "Yelling B...\n";
210 $baz_b->yell;
211
212 You would see something like
213
214 Yodeling...
215 Observation A from [Foo=HASH(0x80f7acc)]
216 Yelling A...
217 Observation B from [Baz=HASH(0x815c2b4)]
218 Observation A from [Baz=HASH(0x815c2b4)]
219 Yelling B...
220 Observation C from [Baz=HASH(0x815c344)]
221 Observation B from [Baz=HASH(0x815c344)]
222 Observation A from [Baz=HASH(0x815c344)]
223
224 And since "Bar" is a child of "Foo" and each has one class-level
225 observer, running either:
226
227 my @observers = Baz->get_observers();
228 my @observers = $baz_a->get_observers();
229
230 would return a two-item list. The first item would be the "observer_b"
231 code reference, the second the "observer_a" code reference. Running:
232
233 my @observers = $baz_b->get_observers();
234
235 would return a three-item list, including the observer for that
236 specific object ("observer_c" coderef) as well as from its class (Baz)
237 and the parent (Foo) of its class.
238
239 Observers
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
257 observations.
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 This class has a "DESTROY" method which must run when an instance of an
297 observable class goes out of scope in order to clean up the observers
298 added to that instance.
299
300 If there is no other destructor in the inheritance tree, this will end
301 up happening naturally and everything will be fine.
302
303 If it does not get called, then the list of observers will leak (which
304 also prevents the observers in it from being garbage-collected) and may
305 become associated with a different instance created later at the same
306 memory address as a previous instance.
307
308 This may happen if a class needs its own "DESTROY" method when it also
309 wants to inherit from Class::Observer (even indirectly!), because perl
310 only invokes the single nearest inherited "DESTROY".
311
312 The most straightforward (but maybe not best) way to ensure that the
313 destructor is called is to do something like this:
314
315 # in My::Class
316 sub DESTROY {
317 # ...
318 $self->Class::Observable::DESTROY;
319 # ...
320 }
321
322 A better way may be to to write all destructors in your class hierarchy
323 with the expectation that all of them will be called (which would
324 usually be preferred anyway) and then enforcing that expectation by
325 writing all of them as follows:
326
327 use mro;
328 sub DESTROY {
329 # ...
330 $self->maybe::next::method;
331 # ...
332 }
333
334 (Perl being Perl, of course, there are many other ways to go about
335 this.)
336
338 notify_observers( [ $action, @params ] )
339
340 Called from the observed item, this method sends a message to all
341 observers that a state-change has occurred. The observed item can
342 optionally include additional information about the type of change that
343 has occurred and any additional parameters @params which get passed
344 along to each observer. The observed item should indicate in its API
345 what information will be passed along to the observers in $action and
346 @params.
347
348 Returns: Nothing
349
350 Example:
351
352 sub remove {
353 my ( $self ) = @_;
354 eval { $self->_remove_item_from_datastore };
355 if ( $@ ) {
356 $self->notify_observers( 'remove-fail', error_message => $@ );
357 } else {
358 $self->notify_observers( 'remove' );
359 }
360 }
361
362 add_observer( @observers )
363
364 Adds the one or more observers (@observer) to the observed item. Each
365 observer can be a class name, object or subroutine -- see "Types of
366 Observers".
367
368 Returns: The number of observers now observing the item.
369
370 Example:
371
372 # Add a salary check (as a subroutine observer) for a particular
373 # person
374 my $person = Person->fetch( 3843857 );
375 $person->add_observer( \&salary_check );
376
377 # Add a salary check (as a class observer) for all people
378 Person->add_observer( 'Validate::Salary' );
379
380 # Add a salary check (as an object observer) for all people
381 my $salary_policy = Company::Policy::Salary->new( 'pretax' );
382 Person->add_observer( $salary_policy );
383
384 delete_observer( @observers )
385
386 Removes the one or more observers (@observer) from the observed item.
387 Each observer can be a class name, object or subroutine -- see "Types
388 of Observers".
389
390 Note that this only deletes each observer from the observed item
391 itself. It does not remove observer from any parent classes. Therefore,
392 if an observer is not registered directly with the observed item
393 nothing will be removed.
394
395 Returns: The number of observers now observing the item.
396
397 Examples:
398
399 # Remove a class observer from an object
400 $person->delete_observer( 'Lech::Ogler' );
401
402 # Remove an object observer from a class
403 Person->delete_observer( $salary_policy );
404
405 delete_all_observers()
406
407 Removes all observers from the observed item.
408
409 Note that this only deletes observers registered directly with the
410 observed item. It does not clear out observers from any parent classes.
411
412 WARNING: This method was renamed from "delete_observers". The
413 "delete_observers" call still works but is deprecated and will
414 eventually be removed.
415
416 Returns: The number of observers removed.
417
418 Example:
419
420 Person->delete_all_observers();
421
422 get_observers()
423
424 Returns all observers for an observed item, as well as the observers
425 for its class and parents as applicable. See "Observable Classes and
426 Objects" for more information.
427
428 Returns: list of observers.
429
430 Example:
431
432 my @observers = Person->get_observers;
433 foreach my $o ( @observers ) {
434 print "Observer is a: ";
435 print "Class" unless ( ref $o );
436 print "Subroutine" if ( ref $o eq 'CODE' );
437 print "Object" if ( ref $o and ref $o ne 'CODE' );
438 print "\n";
439 }
440
441 copy_observers( $copy_to_observable )
442
443 Copies all observers from one observed item to another. We get all
444 observers from the source, including the observers of parents. (Behind
445 the scenes we just use "get_observers()", so read that for what we
446 copy.)
447
448 We make no effort to ensure we don't copy an observer that's already
449 watching the object we're copying to. If this happens you will appear
450 to get duplicate observations. (But it shouldn't happen often, if
451 ever.)
452
453 Returns: number of observers copied
454
455 Example:
456
457 # Copy all observers of the 'Person' class to also observe the
458 # 'Address' class
459
460 Person->copy_observers( Address );
461
462 # Copy all observers of a $person to also observe a particular
463 # $address
464
465 $person->copy_observers( $address )
466
467 count_observers()
468
469 Counts the number of observers for an observed item, including ones
470 inherited from its class and/or parent classes. See "Observable Classes
471 and Objects" for more information.
472
474 APIs for "java.util.Observable" and "java.util.Observer". (Docs below
475 are included with JDK 1.4 but have been consistent for some time.)
476
477 <http://java.sun.com/j2se/1.4/docs/api/java/util/Observable.html>
478
479 <http://java.sun.com/j2se/1.4/docs/api/java/util/Observer.html>
480
481 "Observer and Observable", Todd Sundsted,
482 <http://www.javaworld.com/javaworld/jw-10-1996/jw-10-howto_p.html>
483
484 "Java Tip 29: How to decouple the Observer/Observable object model",
485 Albert Lopez, <http://www.javaworld.com/javatips/jw-javatip29_p.html>
486
488 Class::ISA
489
490 Class::Trigger
491
492 Aspect
493
495 Aristotle Pagaltzis <pagaltzis@gmx.de>
496
497 Chris Winters
498
500 This documentation is copyright (c) 2002-2004 Chris Winters.
501
502 This software is copyright (c) 2021 by Aristotle Pagaltzis.
503
504 This is free software; you can redistribute it and/or modify it under
505 the same terms as the Perl 5 programming language system itself.
506
507
508
509perl v5.36.0 2022-08-18 Class::Observable(3)