The Decorator Pattern: Key Features
Intent:
Attach additional responsibilities to an object dynamically.
Problem:
The object that you want to use does the basic functions you require. However, you may need to add some additional functionality to the object, occurring before or after the object's base functionality. Note that the Java foundation classes use the Decorator pattern extensively for I/O handling.
Solution:
Allows for extending the functionality of an object without resorting to subclassing.
Participants and Collaborators:
The ConcreteComponent is the class having function added to it by the Decorators. Sometimes classes derived from ConcreteComponent are used to provide the core functionality, in which case Concrete-Component is no longer concrete, but rather abstract. The Component defines the interface for all of these classes to use.
Consequences:
Functionality that is to be added resides in small objects. The advantage is the ability to dynamically add this function before or after the functionality in the ConcreteComponent. Note: While a decorator may add its functionality before or after that which it decorates, the chain of instantiation always ends with the ConcreteComponent.
Implementation:
Create an abstract class that represents both the original class and the new functions to be added to the class. In the decorators, place the new function calls before or after the trailing calls to get the correct order.
Intent:
Allows you to use different business rules or algorithms depending upon the context in which they occur.
Problem:
The selection of an algorithm that needs to be applied depends upon the client making the request or the data being acted upon. If you simply have a rule in place that does not change, you do not need a Strategy pattern.
Solution:
Separates the selection of algorithm from the implementation of the algorithm. Allows for the selection to be made based upon context.
Participants and Collaborators:
1. The strategy specifies how the different algorithms are used.
2. The concreteStrategies implement these different algorithms.
3. The Context uses the specific ConcreteStrategy with a reference of type Strategy. The strategy and Context interact to implement the chosen algorithm (sometimes the strategy must query the Context). The Context forwards requests from its Client to the Strategy.
Consequences :
1. The Strategy pattern defines a family of algorithms.
2. Switches and/or conditionals can be eliminated.
3. You must invoke all algorithms in the same way (they must all have the same interface). The interaction between the ConcreteStrategies and the Context may require the addition of getstate type methods to the Context.
Implementation:
Have the class that uses the algorithm (the Context) contain an abstract class (the stragegy) that has an abstract method specifying how to call the algorithm. Each derived class implements the algorithm as needed. Note: this method wouldn't be abstract if you wanted to have some default behavior.
Note:
In the prototypical Strategy pattern, the responsibility for selecting the particular implementation to use is done by the Client object and is given to the context of the Strategy pattern.