1Class::Observable(3)  User Contributed Perl Documentation Class::Observable(3)
2
3
4

NAME

6       Class::Observable - Allow other classes and objects to respond to
7       events in yours
8

SYNOPSIS

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

DESCRIPTION

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

METHODS

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

RESOURCES

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

SEE ALSO

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

AUTHOR

496       Chris Winters <chris@cwinters.com>
497
498
499
500perl v5.8.8                       2004-10-16              Class::Observable(3)
Impressum