The Observer design pattern is used in many applications. If you are unfamiliar with it, or need to remind yourself about the specifics, you can read about it at Wikipedia or MSDN. Caplin Trader even provides a helper class to take care of a lot of the boiler plate code: caplin.core.Observable.
The purpose of the Observer design pattern is to allow one object to notify other objects of events – usually to do with changes to its state.
One common problem I have encountered however is what to do when an Observer is first registered, since the object that it is observing may already be in a particular state.
There are two obvious approaches to this problem.
- The object registering the Observer must check what the state of the object it wants to Observe is after the registration and handle the implications of this (e.g. enabling/disabling parts of the GUI). The main issue I have with this is that it can mean that I end up with two code paths, one to do something before the Observer has been registered and one for the event notifications. In the case where there are lots of different types of Observers for the same object this will introduce a lot of extra code paths – and eventually someone is bound to forget to handle the initial state and thus introduce a bug. In a multi-threaded environment this may become more complicated, particularly if you want to ensure that you only receive an event once.
- When the Observer is registered it is notified of the current state of the object it is observing. Although this is not a standard part of the design pattern, I have found it useful since you only have one code path within the Observer for handling the events.
The following example demonstrates how the second approach can easily be implemented in JavaScript (using caplin.core.Observable).
caplin.namespace("caplinx"); caplin.include("caplin.core.Observable"); caplinx.Trade = function() { this.m_bExecuted = false; this.m_oObservable = new caplin.core.Observable(); }; caplinx.Trade.prototype.addTradeListener = function(oListener) { this.m_oObservable.addObserver(oListener); // ********************************************** // if we have already executed the trade notify the newly added // listener immediately if (this.m_bExecuted) { oListener.executed(); } // ********************************************** }; caplinx.Trade.prototype.execute = function() { // code to handle trade execution ... this.m_bExecuted = true; // notify all listeners that the trade has executed this.m_oObservable.notifyObservers("executed"); }
The technique suggested here is not necessarily appropriate for all Observer design pattern implementations, however I have found it useful to consider when I am writing a new class that will be observed by others.
One thing that I forgot to mention is that if you implement the behaviour described here you must document it so that users of the API are aware that simply registering the listener might result in callback methods being invoked on it, which could have an undesirable effect if the listener is not fully instantiated.