Learning Design Patterns

Monday, April 23, 2007

Visitor


Visitors make use of the interface of Elements to implement a common operation. The advantage of a Visitor over an Iterator is that it can visit Elements from other interfaces.

State

Sometimes, the operations of an object is based on a certain state. Then the State pattern helps:

In the figure, the Request() can be different when Context has different States. And the State can be dynamically changed. The advantages are:
  • It localize the state-specific behavior and partitions operations for different states.
  • It makes state transition explicit.
  • States objects can be shared.
The creation of State objects can be managed by a pool manager if needed.

Observer

There might be several represetations for an object. When the state of the object changes, the represetations should all be updated. A basic model is to register each representation to the object and the object inform them when necessary. These represetations are instances of Observer model, which is presented in the following figure:

The Observer decouples the representation of data and the data themselves. The broadcast model can be modified so as to be more efficient in some cases.

Sometimes, an Observer might observe several Subjects, then it has to look up for whoever has changed when it gets a request. To manage a complicated updating procedure of several objects, it'd be better to adopt a manager so abate the expense of frequent calling Observers.

Memento

Sometimes it is necessary to keep a copy of the internal state of a certain object. However, we can't get the internal state directly, which breaks the encapsulation. Thus the pattern of Memento helps.

As is seen in the figure above, we don't violate the encapsulation. The only problem might be that creating a memento might be expensive in time/storage. Usually the shots of states are maintained so as to recover the original state when necessary.

Mediator

Several objects have to be changed simultaneously however they do not form a hiararchy as in the Chain of Responsibility. If they communicate with each other, they have to keep a record of each other. A convenient way is to introduce a Mediator to loosen up their coupling.

However, now the ConcreteMediator must keep a record of all Collegues. Each ConcreteCollegue inform the Mediator by passing its pointer. The advantages of a Meditator are
  • It limits subclassing of Collegues.
  • It centralizes controls.
  • The communication of Collegues become easier.
In reality the interface of Meditator is not indispensable.

Iterator

Iterator patterns are common in STL. They provide a uniform and simple way of traversing a complicated object, such as a graph. The interaction of an iteration and the object can be divided into two groups: If the iterator itself controls the traversing procedure, it is called an external iterator while if the object controls it, it is called an internal iterator.

Usually, different ConcreteIterators can be applied to traverse the ConcreteAggregate in different styles. A robust iterator should ensure modification of ConcreteAggregate during traversal won't hinder itself. The polymorphism of Iterator is not really necessary sometimes, as STL has told us.

The Iterator must know a lot about the object it traverses hence they are tightly coupled. We should avoid giving too much privilege to the Iterator by making them friends if we are writing a library in which new iterators can be added by users.

Interpreter

The Interpreter is simply a Composite. They have the same sructure while differs a little in motivation. As is introduced in the earlier entry, object in Composite pattern can be treated equivalently, both simple ones and complicated ones made up of simple ones. The Interpreter aims at building an interpreter for a specific language used in a compiler/interpreter (e.g. for Fortran/perl). The simple objects are those terminals while the Composites are non-terminal expressions.