Patterns are a powerful tool in the software development toolbox, because they provide documentation not only of solutions to problems, but solutions that already have successful track records. Therefore there are at least two concrete ways in which they can help us to be more effective in designing software:
First, we can draw on patterns as a source of documented experience when doing our design. Second, seeing known patterns occurring in software once we have designed it, leaves us with a good feeling about what we have produced; that is, we can have increased confidence that our design is sensible, because we know we have used approaches that have already been proven to work well!
I'm sure it will not be controversial to say that the best known book about patterns within the development community in general is the "GoF book" [ Gamma1995 ], a work presenting a catalogue of twenty-three object oriented design patterns. Patterns are at their most effective when working together in collaboration, and while there is much to recommend this book, it has the drawback of failing to point out many effective collaborations.
There are a number of ways for patterns to collaborate. For example, in their original (Alexandrian) setting each pattern was an element of a pattern language [ Alexander1977 ]. Another way involves patterns working together in teams, as Ralph Johnson describes in his article "How Patterns Work in Teams", an article that can be found in [ Rising1998 ].
Now, in object oriented software design, two (of the many) problems that arise often are:
How can an object notify others of changes in its state?
How, at run time, a client can treat a group of objects uniformly - that is how can the group be made to appear as one object from the client's perspective?
OBSERVER Pattern addresses the first of these, and COMPOSITE Pattern the second - both being documented (and described more fully) in the GoF book. This article is about these two patterns. First, it will recap on the two patterns themselves by presenting a brief summary of each. Second, it will describe how design can potentially benefit from their collaboration.
The purpose of the OBSERVER Pattern is to allow updates to the state of an object to be notified to others automatically. The following diagram shows the basic configuration.
SUBJECT is the role name for an object that is to notify others of updates to their state, OBSERVER is the role name for objects that are notified of state updates in their SUBJECT, and Update is the method that serves as notification handler. In order to keep coupling between SUBJECTs and OBSERVERs to a minimum, the role of OBSERVER is crystallised as an interface.
The purpose of the COMPOSITE Pattern is to allow clients to treat objects and compositions of objects uniformly. The following diagram shows the basic configuration.
All objects that are to be treated uniformly support the same design type interface Component. An object that holds a collection of COMPONENTs - COMPOSITECOMPONENT - also supports the COMPONENT interface. The implementation of each method in COMPOSITECOMPONENT simply forwards method invocations to each object in the collection. Therefore, the client actually deals with a collection of objects, but from the client's perspective it deals with one.
When it comes to implementing the OBSERVER Pattern, several issues arise, but there is one in particular that is of interest here: the SUBJECT must bear the weight of the "machinery" needed to notify between zero and many OBSERVERs. Actually, it is fair to put it more strongly: in order to allow itself to be observed, the SUBJECT must commit the design sin of assuming a dual role, i.e. its design role plus that of notifying OBSERVERs of state updates. This issue can therefore be elevated to problem status, and stated as follows: how can the SUBJECT be relieved of its extra responsibility and consequent machinery?
Obviously the SUBJECT can not be relieved of all such machinery, but the machinery can be simplified: instead of the SUBJECT talking to between zero and many OBSERVERs, let it talk to only one - a COMPOSITEOBSERVER! The diagram on the following page shows the transformation in the configuration.
The SUBJECT's collection of OBSERVERs is replaced by a one to one relationship with a single COMPOSITEOBSERVER, used via an association with the OBSERVER interface. This has indeed afforded the benefit of the SUBJECT having a one to one association with a single OBSERVER. Therefore, a COMPOSITEOBSERVER can now be substituted transparently. However, this transformation has consequences both in favour of it and against it. Consequences in its favour are:
The SUBJECT is simplified by the separation of concerns - putting it another way, although the (unavoidable) notification machinery is still in the system, the configuration has been transformed such that the SUBJECT is no longer burdened by it.
The notification mechanism can be tested independently.
The SUBJECT can send update notifications without worrying about the possibility of there being zero OBSERVERs: it's up to the COMPOSITEOBSERVER to handle it.
So far so good, but you don't get anything for nothing. The consequences against are:
The boundary of encapsulation has moved: the mechanism for attaching and detaching OBSERVERs will leak into the client code.
The OBSERVER/COMPOSITE collaboration is just one of many examples of collaborations between two or more (object oriented design) patterns. Further, it is just one example of how the OBSERVER Pattern can collaborate with others.
The collaboration solves one problem: that of the SUBJECT being burdened by the OBSERVER notification mechanism. However it brings with it another problem - that of mechanism leakage. Perhaps collaboration with another design pattern such as FAÇADE [ Gamma1995 ] could be used to address this resulting problem...(?)
[Alexander1977] Christopher Alexander, Sara Ishikawa and Murray Silverstein with Max Jacobson, Ingrid Fiksdahl-King and Shlomo Angel, A Pattern Language: Towns, Buildings, Construction , Oxford University Press, 1977.
[Gamma1995] Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software , Addison-Wesley, 1995.
[Rising1998] Editor Linda Rising, The Patterns Handbook , Cambridge University Press.