Published May 2, 2020
by Doug Klugh
Promoting Extensibility
Extend functionality by adding properties and behaviors to individual objects instead of entire classes. While inheritance can be used to statically add responsibilities to every subclass instance, decorating individual objects dynamically provides much greater flexibility. This is achieved by enclosing a component within a decorator, which conforms to the interface of the component and provides transparency to the clients of that component. This transparency enables an unlimited number of added responsibilities.
Decorators offer what may be thought of as an à la carte approach to extending functionality. Start with a small, simple class, then add or remove functionality (at run-time) as needed with a decorator. This avoids having to anticipate all of the responsibilities that will be needed with a large, complex, static class. This also avoids using inheritance to create static sub-classes for every new responsibility that you anticipate ever needing. As you can imagine, you could easily end up with a ton of classes, significantly increasing the complexity of your system. On the other hand, using decorators gives you the flexibility to mix and match functionality as needed.
The Decorator Pattern and the Strategy Pattern both provide dynamic alternatives to subclassing. A good way to distinguish these patterns is to remember that a decorator effectively changes the skin of an object, while a strategy changes its guts. Strategies are used to configure classes that differ only in their behavior. One example would be to implement different algorithms to address different performance requirements.