Decorator Pattern: Structure and Participants
The Decorator Pattern consists of four key participants that work together to enable dynamic behavior composition.
+ addedBehavior(): void
+ addedState: Type
Participant Responsibilities:
1. Component (Interface/Abstract Class): Defines the common interface for both concrete components and decorators. This ensures that decorators can be used wherever the original object is expected. All participants must implement operation() to maintain substitutability.
2. ConcreteComponent: The original object to which new responsibilities can be added. It implements the base operation() with core functionality. This is the object being wrapped by decorators. In a coffee shop example, this would be Espresso or DarkRoast.
3. Decorator (Abstract): Maintains a reference to a Component object and implements the Component interface. It forwards requests to the wrapped component by default. Concrete decorators extend this class. This is the key to composition: the decorator HAS-A component (composition) rather than IS-A component (inheritance).
4. ConcreteDecorator: Adds specific responsibilities to the component. It calls the wrapped component's operation() and adds its own behavior before or after. Each concrete decorator can add new methods (addedBehavior()) or state (addedState). Examples include MilkDecorator, WhipDecorator.
Method Call Flow:
When operation() is called on a decorated object: First, the outermost decorator receives the call. Second, it may perform preprocessing. Third, it delegates to the wrapped component's operation(). Fourth, the wrapped component (which might itself be a decorator) continues the chain. Fifth, the outermost decorator performs postprocessing if needed. Sixth, the result returns up the chain.