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
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

DESCRIPTION

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

METHODS

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

RESOURCES

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

SEE ALSO

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

AUTHOR

492       Chris Winters <chris@cwinters.com>
493
494
495
496perl v5.32.0                      2020-07-28              Class::Observable(3)
Impressum