Observer
Intent
Define a one-to-many dependency between objects so that when one object
changes state, all its dependents are notified and updated
automatically.
Problem
A large monolithic design does not scale well as new graphing or
monitoring requirements are levied.
Discussion
Define an object that is the "keeper" of the data model and/or business
logic (the Subject). Delegate all "view" functionality to decoupled and
distinct Observer objects. Observers register themselves with the
Subject as they are created. Whenever the Subject changes, it
broadcasts to all registered Observers that it has changed, and each
Observer queries the Subject for that subset of the Subject's state
that it is responsible for monitoring.
This allows the number and "type" of "view" objects to be configured
dynamically, instead of being statically specified at compile-time.
The protocol described above specifies a "pull" interaction model. Instead
of the Subject "pushing" what has changed to all Observers, each Observer is
responsible for "pulling" its particular "window of interest" from the
Subject. The "push" model compromises reuse, while the "pull" model is
less efficient.
Issues that are discussed, but left to the discretion of the designer,
include: implementing event compression (only sending a single change
broadcast after a series of consecutive changes has occurred), having a
single Observer monitoring multiple Subjects, and ensuring that a
Subject notify its Observers when it is about to go away.
The Observer pattern captures the lion's share of the Model-View-Controller
architecture that has been a part of the Smalltalk community for years.
Example
The Observer defines a one-to-many relationship so that when one object
changes state, the others are notified and updated automatically. Some
auctions demonstrate this pattern. Each bidder possesses a numbered
paddle that is used to indicate a bid. The auctioneer starts the
bidding, and "observes" when a paddle is raised to accept the bid. The
acceptance of the bid changes the bid price which is broadcast to all
of the bidders in the form of a new bid. [Michael Duell, "Non-software
examples of software design patterns", Object Magazine,
Jul 97, p54]
Rules of thumb
Chain of Responsibility, Command, Mediator, and Observer, address how
you can decouple senders and receivers, but with different trade-offs.
Chain of Responsibility passes a sender request along a chain of
potential receivers. Command normally specifies a sender-receiver
connection with a subclass. Mediator has senders and receivers
reference each other indirectly. Observer defines a very decoupled
interface that allows for multiple receivers to be configured at
run-time. [GOF, p347]
Mediator and Observer are competing patterns. The difference between
them is that Observer distributes communication by introducing
"observer" and "subject" objects, whereas a Mediator object
encapsulates the communication between other objects. We've found it
easier to make reusable Observers and Subjects than to make reusable
Mediators. [GOF, p346]
On the other hand, Mediator can leverage Observer for dynamically
registering colleagues and communicating with them. [GOF, p282]