If you have ever used Java, you may have run across the java.util.Observable class and the java.util.Observer interface. With them you can decouple an object from the one or more objects that wish to be notified whenever particular events occur.

These events occur based on a contract with the observed item. They may occur at the beginning, in the middle or end of a method. In addition, the object knows that it is being observed. It just does not know how many or what types of objects are doing the observing. It can therefore control when the messages get sent to the obsevers.

The behavior of the observers is up to you. However, be aware that we do not do any error handling from calls to the observers. If an observer throws a die, it will bubble up to the observed item and require handling there. So be careful.

Throughout this documentation we refer to an 'observed item' or 'observable item'. This ambiguity refers to the fact that both a class and an object can be observed. The behavior when notifying observers is identical. The only difference comes in which observers are notified. (See "Observable Classes and Objects" for more information.)

The observable item does not need to implement any extra methods or variables. Whenever it wants to let observers know about a state-change or occurrence in the object, it just needs to call notify_observers().

As noted above, whether the observed item is a class or object does not matter -- the behavior is the same. The difference comes in determining which observers are to be notified:

If the observed item is a class, all objects instantiated from that class will use these observers. In addition, all subclasses and objects instantiated from the subclasses will use these observers.

If the observed item is an object, only that particular object will use its observers. Once it falls out of scope then the observers will no longer be available. (See "Observable Objects and DESTROY" below.)

Whichever you chose, your documentation should make clear which type of observed item observers can expect.

Previous versions of this module had a problem with maintaining references to observable objects/coderefs. As a result they'd never be destroyed. As of 1.04 we're using weak references with weaken in Scalar::Util so this shouldn't be a problem any longer.

Called from the observed item, this method sends a message to all observers that a state-change has occurred. The observed item can optionally include additional information about the type of change that has occurred and any additional parameters @params which get passed along to each observer. The observed item should indicate in its API what information will be passed along to the observers in $action and @params.

Removes the one or more observers (@observer) from the observed item. Each observer can be a class name, object or subroutine -- see "Types of Observers".

Note that this only deletes each observer from the observed item itself. It does not remove observer from any parent classes. Therefore, if an observer is not registered directly with the observed item nothing will be removed.

Copies all observers from one observed item to another. We get all observers from the source, including the observers of parents. (Behind the scenes we just use get_observers(), so read that for what we copy.)

We make no effort to ensure we don't copy an observer that's already watching the object we're copying to. If this happens you will appear to get duplicate observations. (But it shouldn't happen often, if ever.)

Returns: number of observers copied

Example:

# Copy all observers of the 'Person' class to also observe the
# 'Address' class
Person->copy_observers( Address );
# Copy all observers of a $person to also observe a particular
# $address
$person->copy_observers( $address )

count_observers()

Counts the number of observers for an observed item, including ones inherited from its class and/or parent classes. See "Observable Classes and Objects" for more information.

Note that the debugging messages will try to get information about the observed item if called from an object. If you have an id() method in the object its value will be used in the message, otherwise it will be described as "an instance of class Foo".

SET_DEBUG( $bool )

Turn debugging on or off. If set the built-in implementation of observer_log() will issue a warn at appropriate times during the process.

observer_log( @message )

Issues a warn if SET_DEBUG hsa been called with a true value. This gets called multiple times during the registration and notification process.

To catch the warn calls just override this method.

observer_error( @message )

Issues a die if we catch an exception when notifying observers. To catch the die and do something else with it just override this method.