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
104 package My::Child;
105
106 use strict;
107 use base 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
150 Throughout this documentation we refer to an 'observed item' or
151 'observable item'. This ambiguity refers to the fact that both a class
152 and an object can be observed. The behavior when notifying observers is
153 identical. The only difference comes in which observers are notified.
154 (See "Observable Classes and Objects" for more information.)
155
156 Observable Classes and Objects
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
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 Previous versions of this module had a problem with maintaining
296 references to observable objects/coderefs. As a result they'd never be
297 destroyed. As of 1.04 we're using weak references with "weaken" in
298 Scalar::Util so this shouldn't be a problem any longer.
299
301 Observed Item Methods
302 notify_observers( [ $action, @params ] )
303
304 Called from the observed item, this method sends a message to all
305 observers that a state-change has occurred. The observed item can
306 optionally include additional information about the type of change that
307 has occurred and any additional parameters @params which get passed
308 along to each observer. The observed item should indicate in its API
309 what information will be passed along to the observers in $action and
310 @params.
311
312 Returns: Nothing
313
314 Example:
315
316 sub remove {
317 my ( $self ) = @_;
318 eval { $self->_remove_item_from_datastore };
319 if ( $@ ) {
320 $self->notify_observers( 'remove-fail', error_message => $@ );
321 }
322 else {
323 $self->notify_observers( 'remove' );
324 }
325 }
326
327 add_observer( @observers )
328
329 Adds the one or more observers (@observer) to the observed item. Each
330 observer can be a class name, object or subroutine -- see "Types of
331 Observers".
332
333 Returns: The number of observers now observing the item.
334
335 Example:
336
337 # Add a salary check (as a subroutine observer) for a particular
338 # person
339 my $person = Person->fetch( 3843857 );
340 $person->add_observer( \&salary_check );
341
342 # Add a salary check (as a class observer) for all people
343 Person->add_observer( 'Validate::Salary' );
344
345 # Add a salary check (as an object observer) for all people
346 my $salary_policy = Company::Policy::Salary->new( 'pretax' );
347 Person->add_observer( $salary_policy );
348
349 delete_observer( @observers )
350
351 Removes the one or more observers (@observer) from the observed item.
352 Each observer can be a class name, object or subroutine -- see "Types
353 of Observers".
354
355 Note that this only deletes each observer from the observed item
356 itself. It does not remove observer from any parent classes. Therefore,
357 if an observer is not registered directly with the observed item
358 nothing will be removed.
359
360 Returns: The number of observers now observing the item.
361
362 Examples:
363
364 # Remove a class observer from an object
365 $person->delete_observer( 'Lech::Ogler' );
366
367 # Remove an object observer from a class
368 Person->delete_observer( $salary_policy );
369
370 delete_all_observers()
371
372 Removes all observers from the observed item.
373
374 Note that this only deletes observers registered directly with the
375 observed item. It does not clear out observers from any parent classes.
376
377 WARNING: This method was renamed from "delete_observers". The
378 "delete_observers" call still works but is deprecated and will
379 eventually be removed.
380
381 Returns: The number of observers removed.
382
383 Example:
384
385 Person->delete_all_observers();
386
387 get_observers()
388
389 Returns all observers for an observed item, as well as the observers
390 for its class and parents as applicable. See "Observable Classes and
391 Objects" for more information.
392
393 Returns: list of observers.
394
395 Example:
396
397 my @observers = Person->get_observers;
398 foreach my $o ( @observers ) {
399 print "Observer is a: ";
400 print "Class" unless ( ref $o );
401 print "Subroutine" if ( ref $o eq 'CODE' );
402 print "Object" if ( ref $o and ref $o ne 'CODE' );
403 print "\n";
404 }
405
406 copy_observers( $copy_to_observable )
407
408 Copies all observers from one observed item to another. We get all
409 observers from the source, including the observers of parents. (Behind
410 the scenes we just use "get_observers()", so read that for what we
411 copy.)
412
413 We make no effort to ensure we don't copy an observer that's already
414 watching the object we're copying to. If this happens you will appear
415 to get duplicate observations. (But it shouldn't happen often, if
416 ever.)
417
418 Returns: number of observers copied
419
420 Example:
421
422 # Copy all observers of the 'Person' class to also observe the
423 # 'Address' class
424
425 Person->copy_observers( Address );
426
427 # Copy all observers of a $person to also observe a particular
428 # $address
429
430 $person->copy_observers( $address )
431
432 count_observers()
433
434 Counts the number of observers for an observed item, including ones
435 inherited from its class and/or parent classes. See "Observable Classes
436 and Objects" for more information.
437
438 Debugging Methods
439 Note that the debugging messages will try to get information about the
440 observed item if called from an object. If you have an "id()" method in
441 the object its value will be used in the message, otherwise it will be
442 described as "an instance of class Foo".
443
444 SET_DEBUG( $bool )
445
446 Turn debugging on or off. If set the built-in implementation of
447 "observer_log()" will issue a warn at appropriate times during the
448 process.
449
450 observer_log( @message )
451
452 Issues a "warn" if "SET_DEBUG" hsa been called with a true value. This
453 gets called multiple times during the registration and notification
454 process.
455
456 To catch the "warn" calls just override this method.
457
458 observer_error( @message )
459
460 Issues a "die" if we catch an exception when notifying observers. To
461 catch the "die" and do something else with it just override this
462 method.
463
465 APIs for "java.util.Observable" and "java.util.Observer". (Docs below
466 are included with JDK 1.4 but have been consistent for some time.)
467
468 <http://java.sun.com/j2se/1.4/docs/api/java/util/Observable.html>
469
470 <http://java.sun.com/j2se/1.4/docs/api/java/util/Observer.html>
471
472 "Observer and Observable", Todd Sundsted,
473 <http://www.javaworld.com/javaworld/jw-10-1996/jw-10-howto_p.html>
474
475 "Java Tip 29: How to decouple the Observer/Observable object model",
476 Albert Lopez, <http://www.javaworld.com/javatips/jw-javatip29_p.html>
477
479 Class::ISA
480
481 Class::Trigger
482
483 Aspect
484
486 Copyright (c) 2002-2004 Chris Winters. All rights reserved.
487
488 This library is free software; you can redistribute it and/or modify it
489 under the same terms as Perl itself.
490
492 Chris Winters <chris@cwinters.com>
493
494
495
496perl v5.30.1 2020-01-29 Class::Observable(3)