Design Patterns: Elements of Reusable Object-Oriented Systems
By: E. Gamma, R. Helm, R. Johnson, J. Vlissides
Published in: Addison-Wesley, 1995
Summary: Describes simple and elegant solutions to problems in object-oriented design.
Pattern: Abstract Factory
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
Separate construction of a complex object from its representation so that the same construction process can create different representations.
- Abstract Factory is similar to this pattern. Both construct complex objects. Builder focuses on constructing a complex object step by step, while Abstract Factory focuses on families of product objects. Builder returns the complete product as a final step, while Abstract Factory returns each product object as it is created.
Pattern: Factory Method
Define an interface for creating an object, but let subclasses decide which class to instantiate. This allows a class to defer instantiation to subclasses.
Specify the kinds of objects to create using a prototypical instance, and create objects by copying this prototype.
- A command copied before being placed on the history list is a Prototype
Ensure a class only has one instance, and provide a global point of access to it.
Convert the interface of a class to one expected by clients. This lets classes work together that couldn't otherwise because of incompatible interfaces.
- An adapter can be a command, translating messages between the client and adaptee.
- Bridge has a similar structure but a different intent. Bridge separates interface from implementation; Adapter changes the interface to an object.
- Decorator enhances another object without changing its interface, so it is more transparent to the application than this pattern. Decorator also supports recursive composition.
- Facade defines a new interface, while this pattern reuses an old interface.
- Proxy defines a representative or surrogate for another object but does not change its interface.
Decouple an abstraction from its implementation so the two can vary independently.
- An Abstract Factory can create and configure a Bridge
- Adapter helps unrelated classes work together and is usually applied to existing systems. This pattern is applied up-front.
Compose objects into tree structures to represent part-whole hierarchies. Clients can then treat individual objects and compositions of objects uniformly.
- Often the component-parent link is used in Chain of Responsibility
- This pattern can implement MacroCommands.
- Decorator is often used with this pattern, usually with a common parent class.
- Iterator can traverse a Composite structure.
- Visitor localizes operations and behavior that would otherwise be distributed across Composite and Leaf classes.
Attach additional responsibilities to an object dynamically. This provides a flexible alternative to subclassing for extending functionality.
- This pattern only changes an object's responsibilities, not its interface. Adapter provides a new interface for an object.
- This pattern can be considered a degenerate Composite with one component; however, this pattern adds additional responsibilities and is not intended for object aggregation.
- This pattern can be confused with Proxy. A Proxy doesn't generally change the subject's behavior except to make it available or unavailable.
Provide a unified interface to a set of interfaces in a subsystem. A facade defines a higher-level interface that makes the subsystem easier to use.
- Abstract Factory can be used with this pattern to provide an interface for creating subsystem objects in a subsystem-independent way.
- This pattern defines a new interface, while Adapter reuses an old one.
Use sharing to support large numbers of fine-grained objects efficiently.
- This pattern is often combined with Composite to implement a hierarchical structure as a directed acyclic graph with shared leaf nodes.
- State and Strategy objects are often implemented as flyweights.
Provide a surrogate or placeholder for another object.
- Adapter provides a different interface to an object; Proxy provides the same interface. A protection proxy might refuse to perform an operation that the subject will perform, so its interface may be a subset of the original object's.
- Decorator is similar in structure to this pattern. The ConcreteComponent in Decorator (the RealSubject in Proxy) implements a behavior invoked by a decorator (the Proxy in Proxy). The primary difference between Decorator and Proxy is intent. Decorator adds functionality or provides options for dynamically choosing functionality in addition to the core functionality of ConcreteComponent.
Pattern: Chain of Responsibility
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
- This pattern is often applied with Composite, where a component's parent is its successor.
- EventHandler is an adaptation of this pattern that avoids cyclic link time dependencies.
- This pattern employs Object Recursion
Encapsulate a request as an object, allowing the parameterization of clients with different requests, queue or log requests, and support undoable operations.
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
- The abstract syntax tree example in this pattern is a Composite
- Flyweight can share terminal symbols in the abstract syntax tree.
- An Iterator to traverse the interpreter structure.
- Visitor can maintain the behavior in each node of the abstract syntax tree.
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
- Iterator can traverse a Composite structure.
Define an object that encapsulates how a set of objects interact. Promote loose coupling by keeping objects from referring to each other explicitly.
- Facade abstracts a subsystem to provide an improved interface. Its protocol is unidirectional--the Facade makes requests of the subsystem. Mediator can implement cooperative behavior not provided by colleague objects, and the protocol is multidirectional.
- Colleagues can communicate with the mediator using Observer
Without violating encapsulation, capture and externalize an object's internal state so the object can be restored to the state.
Define a one-to-many dependency between objects so that when one object changes state, the others are notified and updated automatically.
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
Category: Behavioral, Finite State Machines
- State objects are often implemented as Flyweight objects.
- This pattern can be confused with Strategy. If the context will contain only one of several possible state/strategy objects, use Strategy. If the context may contain many different state/strategy objects, use State. An object is usually put into a state by an external client, while it will choose a strategy on its own.
- Finite State Machine Patterns, MOODS: Models for Object-Oriented Design of State###MOODS, State Patterns
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
- Concrete strategies often make good Flyweight objects.
- Template Method uses inheritance to vary part of an algorithm. Strategy uses delegation to vary the entire algorithm.
- Sponsor-Selector enhances this pattern to pick the best ConcreteStrategy at run-time.
Pattern: Template Method
Define the skeleton of an algorithm, deferring some steps to subclasses. This allows subclasses to redefine certain steps of an algorithm without changing the algorithm's structure.
- Factory Methods are often called by a Template Method.
- This pattern uses inheritance to vary part of an algorithm. Strategy uses delegation to vary the entire algorithm.
Pattern: Hook Method
Contains: Hook Method [Pree94],
Represent an operation to be performed on the elements of an object structure, letting you define a new operation without changing the classes of the elements on which it operates.
- Visitor can apply an operation over a Composite structure.
- A visitor can implement behavior for each node of an Interpreter