A Survey of Common Design Patterns
Chain of Responsibility
One of the tenets of software engineering is to keep objects loosely coupled. The Chain of Responsibility is intended to promote loose coupling between the sender of a request and its receiver by giving more than one object an opportunity to handle the request. The receiving objects are chained and pass the request along the chain until one of the objects handles it.
The class diagram, as illustrated in the following figure, shows that the client instantiates the Request and passes it as a parameter to an instance of the Handler. Each concrete handler is responsible for implementing an action to take on the Request object, and to maintain a reference to the next handler in the chain. An abstract Handler is defined to provide a uniform interface for the concrete handlers. The client is responsible for creating Request objects and then passing them to the first handler in the chain. The chain (Handler1 -> Handler2 -> Handler3, and so forth) can be set by the client by calling the SetSuccessor(...) for each handler it instantiates.
The Command pattern is intended to encapsulate a request as an object. For example, consider a window application that needs to make requests of objects responsible for the user interface. The client responds to input from the user by creating a command object and the receiver. It then passes this object to an Invoker object, which then takes the appropriate action. This allows the client to make requests without having to know anything about what action will take place. In addition, you can change that action without affecting the client. Practical uses for Command are for creating queues and stacks for supporting "undo" operations, configuration changes, and so on.
As shown in the following class diagram, the client instantiates the Receiver class and passes it as an argument to the constructor of the ConcreteCommand class. The Receiver is responsible for carrying out the specific actions required and fulfilling the request. An abstract class is defined to provide a uniform interface for the concrete Command class. The concrete Command classes are responsible for executing the appropriate methods on the Receiver. The client uses the Invoker to ask the Command when to carry out the request. One drawback to the Command pattern is that it tends to lead to a proliferation of small classes; however, it does lead to simpler clients for supporting modern user interfaces.
The Composite is intended to allow you to compose tree structures to represent whole-part hierarchies so that clients can treat individual objects and compositions of objects uniformly. We often build tree structures where some nodes are containers of other nodes, and other nodes are "leaves." Instead of creating separate client code to manage each type of node, Composite lets a client work with either using the same code.
As the class following diagram shows, the composite pattern consists of an abstract class called a Component, which provides interface for nodes and leaves alike. In addition, the Component may also define a default implementation when it is appropriate. The Leaf and Composite classes provide their own implementations, as well. The key to this pattern is the Composite class, which uses a collection to create complex objects from other objects (Leaves or other Composites). In addition, the composite object provides a way to iterate the composition to execute operations on the individual objects in the composition.
Ordinarily, an object inherits behavior from its subclasses. The decorator pattern is intended to give you a way to extend the behavior of an object, and you can also dynamically compose an object's behavior. Decorator allows you to do so without the need to create new subclasses.
When you examine the next class diagram, you will notice there are two basic types of classes. The Component, whose behavior you want to extend, and the Decorator, which implements the extended behavior. You can have any number of Components and Decorators. You also provide abstract classes for both types of classes so the client has a common interface. The key to the Decorator is the SetComponent(...) method, which takes a component as an argument. The client is responsible for instantiating the Component and passing it to the Decorator's constructor. The client is then free to utilize the Component's new methods, as implemented in the Director. A really nice feature of the Decorator pattern is that you can decorate specific instances of objects. This is difficult to do if you subclass your components directly.
With the many classes and subsystems we use, it is important to isolate our software and reduce coupling. The Facade Pattern is intended to provide a unified interface to a set of interfaces in a subsystem. The Facade defines a higher-level interface that makes the subsystems easier to use. There are several benefits to Facade. First, it provides developers with a common interface to the subsystem, leading to more uniform code. Second, it isolates your system and provides a layer of protection from complexities in your subsystems as they evolve. Third, this protection makes it easier to replace one subsystem with another because the dependencies are isolated. The main disadvantage of Facade is that it tends to limit your flexibility. You are free, however, to instantiate objects directly from the subsystems.
As the following class diagram shows, the facade pattern provides the client with a uniform interface to the subsystem. Often the code that is inside a facade would have to be inside client code without the facade. The subsystem code beneath the facade can change without affecting the client code.
When developing classes, you always provide constructors for your clients' use. There are certain circumstances in which you do not want your clients to know which class out of several to instantiate. The Factory Method is intended to define an interface for clients to use to create an object, but lets subclasses decide which class to instantiate. Factory Methods let a class defer instantiation to subclasses.
As the next class diagram shows, the pattern uses two types of classes. The Product classes, which are the classes that make up your application, and the Creator classes, which are responsible for defining the Factory methods used to create instances of Product objects on the clients behalf. The Creator class defines the factory method, which returns an object of type Product. The patterns uses abstract Product and Creator classes to provide the client with a uniform interface. Concrete classes provide the appropriate implementation for their respective base class. In addition, Creator may also define a default implementation of the factory method that returns a default ConcreteProduct object. It may also call the factory method to create a Product object. Any of these approaches can be used to balance the forces at work on your project.
Page 2 of 5