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.

Command

In GUI applications, it is always desirable to implement the same function via different ways (e.g. menus, context menus and etc.). Hence how can it be possible to separate the invoker and commands themselves in order to avoid unnecessary repeatition of code? The Command pattern provides us more than this.

In this figure, all Commands have the same interface. Each Invoker responds to the Client by sending request to the corresponding ConcreteCommand. The Command then carries out the action to handle the request.

We can maintain a queue for Commands, and the Command should keep all necessary information to undo the action. Thus by adding an Unexecute() to the interface and implementing it in subclasses, a do/undo/redo mechanism can be established.

The advantages are:
  • It decouples the invoker and receiver and they can be modified separately.
  • A Composite of Commands can be built to represent a series of complicated operations.
  • It is easy to add new Commands.

Sunday, April 22, 2007

Chain of Reponsibility

In this setting, a request is send to only one object, however there should be several related objects that take the responsibility. So a chain is build so as to create the final response.

The chain is usually created automatically when Composite pattern is used, since each object might keep a pointer to its parent. So the request sent to a leaf can be propagated further to its parent. The forwarding procedure can also be used to pass the request to who can handle it if the current object can not.

Proxy


At first glance, you may wonder what's the difference of a Proxy and a Decorator? Why should we propose such a pattern? A Decorator is aimed at docorating the original object, that is to provide more functions before or after the operation sent to the object. However, Proxy does not take the trouble to do more than sending the request.

Useless guys, you might wonder. However, you are wrong. The basic usage of a Proxy is to put off the real expense when it is inevitable. That's to say, RealSubject is something once created costing much time. Then its basic information can be obtained and stored in a Proxy object which acts in the same way as RealSubject does. So if only lightweight operations inquring about the basic information, there is no need to instantiate one immediately.

The indirection of Proxy can also be useful in the case of copy-on-write: The Proxy keeps the copied object and the copy needn't be carried out if the original one isn't modified. What's more the Proxy can protect the object in some way.

Friday, April 20, 2007

Flyweight

The Flyweight patterns can be illustrated with the following figure:

In this figure, the Flyweight objects can be divided into two subgroups, according to the states they keep track of. ConcreteFlyweight ones only keep an intrinsic state and the extrinsic state should be computed to locate each one by the Client. It trades off the time cost to the storage cost. Usually, it should be those objects repeated frequently and larged whose extrinsic states are easy to obtained. The UnsharedConcreteFlyweight objects are usually those whose extrinsic states are also stored and won't be necessary to be kept in a pool (since they are seldom repeated).

Sometimes, Flyweight pattern is used with Composite, which then builds a complex objects by these small repeated ones.

Facade

I guess any one who has built a complex (sub)system must be familiar with the idea by providing the user a simple class that carries out routines in the (sub)system so as to centralize the requests forwarded to the (sub)system. This idea relieves the direct coupling between (sub)systems and facilitate the users who can ignore the inner interactions of complicated classes.

Decorator

A Decorator of a certain subclass of an interface is simply a subclass that is on the same inheritance level. The difference between the subclass and its Decorator is that instead of implementing all the nterface operations itself, the Decorator simply maintains an instance of the subclass and forward the request to it after/before it adds decorations to the request. The idea enables decorators can be nested by any sequence without worry about what the decorated one is.

The Decorator helps decrease the height of the class hiararchy and is more flexible than pure inheritance. Sometime the abstract Decorator class can be omitted.

Composite

The Composite pattern is to build a class hiararchy such that each subclasses of it can be treated likewise, no matter it is a single object or a collection of objects. The following figure presents us the main idea:

In the figure, the Leaf subclass is the basic element that can build a Composite object. To implement a common operation to both the Leaf object and the Composite one, it is required that Leaf must implement the operation and Composite can forward the request to its childrens (perhaps a Leaf or a Composite one).

The Leaf class doesn't really need an Add() or Remove() operation, and hence can throw exceptions in these functions. In order to traverse the Composite object more easily, each Component can maintain a pointer to its parent. The children of a Composite object should be destroyed by the object itself in its destructor function by forwarding the request to all its children.

Thursday, April 19, 2007

Bridge

The Bridge pattern has similar motivation as Adapter. However, the Adapter emphasizes the ability to change the interface of a given class while Bridge is supposed to separate the implementation details from the semantics (it seems that the interface of an Adapter is the semantics and the adaptee is the implementation details).

You can often take the Implementor as the Adaptee in Adaptor.

The important result of a Bridge is that the interface and implementation are decoupled and hence are easy to modify in future.

Wednesday, April 18, 2007

Adapter

An Adapter is used for adapting some existent classes to a certain interface. Usually we have two styles of Adapter, one realized with inheritance and the other with delegate.

It is a natural idea to have a class multiplely inherited from the interface and the implemented class. In this way, the inherited class can have a public interface and a private implementation which is intended to hide from the users. Hence the following figure illustrate the idea:


However, the class Adapter has some difficulty if it is used to adapt several Adaptees. In this case the follow method is preferable:

A two-way adapter can make two interfaces transparent.

Tuesday, April 17, 2007

Singleton

Sometime, only one instance of a certain class is needed. In this case, Singleton pattern helps.

In the figure above, the user is required to get the unique instance by calling Instance() which creates and maintains the object. The constructor is usually hidden by setting it protected so that the user can't instantiate it manually.

Of course, the idea can be applied in the case a fixed/variable number of instances are allowed to exists and the user shouldn't get involved in the maintainance of them. Static operations can be used, however it is less flexible because in this case there can be only one instance.

Prototype

In Abstract Factory, the different styles of products are realized in different subclasses of Abstract Factory. Though it is commonly desirable, when mixing different styles together, it is limited. What's more, it leads to too many subclasses. Prototype provides a way to eliminating unnecessary subclassing by adding a Clone() interface. This function is simply a copy constructor. Usually we have an auxiliary Prototype factory/manager (Client) that is instantiated with needed prototypes and produce the demanded parts by calling Clone().

What's more, by changing the Prototype manager dynamically, the products can also change dynamically and locally (which means only part of the products changes).

Factory Method and Template Method

When the sematics requires a procedure instantiate an object from a certain class/interface while the latter has to be instantiated in a specific concrete subclass, it is desirable to leave a pure virtual function in the interface of the former for creation of the object. This interface function must be implemented in the subclasses to create necessary concrete objects needed by the abstract procedure that calls it. Another paraphrase of the function is that it acts as a hook which must be filled in subclasses.

As you might guess, there will be as many subclasses of Creator as those of Product. However, the templates in C++ helps in this case by automating the parallel hiarachies.

The abstract procedure that calls Factory Methods are usually called Template Method, which is illustrated in the following figure:

Monday, April 2, 2007

Builder

What can we do when creating a complex object that consists of lots of small logic/semantic units? The separability of semantic and implementation is required to ensure later maintainance of code. Abstract Factory helps in this way. But as for a complex object, different directors are usually needed to create different versions. Hence it's better separate the directions and basic unit-creating interfaces. After the buiding procedure carried out by directors, the object can be handed to later applications.
Create a builder interface for creating basic units. It might not be a totally abstract class. Its subclasses implements different styles of units. It maintains the object to be built, however without directions, thus it can't build the desired object itself.
Get a director that contains a builder. It maintains the object to be built by delegating all basic building operations to the builder. Its subclasses or itself implement the semantic direction of weaving all units together.
The following picture shows how the two parts interacts with each other:

What's the difference between Abstract Factory and a builder? Well, an Abstract Factory does not maintain a complex objects to be built. In fact, it only provides a unified interface of creating objects of different styles. The Builder, more than providing different styles by subclasses, maintains a complex object, which means a Builder is aimed at building something and the semantic building is delegated to a director which commands the builder do what it wishes to.

Then it has the following cons and pros:
  • It separates different styles of implementation from the semantic weaving.
  • Usually, we have to provide a default building result for the top Builder (the interface).

Abstract Factory

Why should we bother with Abstract Factory? Because it separates implementaton of styles from functions. That's to say, when there are several styles of implementing something, which has nothing to do with logic or semantic functions in an upper level, we can follow the Abstract Factory's idea.
  • For each logic unit, provide an interface that's used for later interaction. Different styles of implementations are subclasses of this interface.
  • Create an interface for creating semantic products (units). Different styles are also implementation of this interface. However each subclass provides fully-functioned interface for creating all products in this style.
Here is a graphical illustration of Abstract Factory:


What are its advantages and disadvantages?
  • If we want to add another style, the current framework can still be used without a change since the interface is fixed.
  • If we want to add another logic/semantic unit, we have to add a function to the interface of Abstract Factory and implements all the styles of this logic/semantic unit. Thus it is a little difficult!
  • Sometimes, there should be only one factory. Hence a singleton should be incorporated with it.
But be sure not to confuse styles and functions!

Tuesday, March 20, 2007

Strategy

Currently I am studying dssign pattern for creating a little ``framework'' for machine learning algorithms. Though it is now too ambitious for me, I decide to learn something through all these failures of designs. Then I happen to find umbrello, a KDE UML designer. I think it is nice even when I can't fully understand it. Here is a diagram exported by it representing the Strategy design pattern.

In the settings above, we want to add a set of typesetting algorithms for composing glyphs. The class(actually an interface) Compositor contains a pointer to what it is required to compose (which I don't know how to express in the UML), a pointer to an instance of Composition. The interface has two functions, one for setting the instance, the other for typeseting algorithms which should be realized by its subclasses, such as ArrayCompositor and TeXCompositor.

The objects of Composition contains a Compositor instance, which is delegated with typesetting work when Insert() is called. As a result, any new typesetting algorithms can be added as a new subclass of Compositor.

This pattern solves the problem of tackling the same problem with different strategies. That is, define a strategy interface which is built on whoever needs, realize the concrete algorithms as its subclasses and delegate the procedure to the aggregated strategy objects. Here is a figure to illustrate the role Strategy plays: