Week 4 - Decorator Design Pattern
The Decorator Design Pattern¶
Classification¶
- Structural Design Pattern
Pattern Definition¶
- Attach additional responsibilities to an object dynamically.
- Think of a decorator WRAPPING around some other object or method.
- Decorators provide a flexible alternative to sub-classing for extending functionality.
- Open/Close Principle: Open for extension and closed to modification.
- Decorator allows for this seemingly contradictory goals, but be CHOOSY when you use it because it can lead to costly, hard-to-understand code.
- The decorator adds its own behavior before and/or after delegating to the object it decorates to do the rest of the job.
Representations¶
Mermaid Graph¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
UML¶
- Decorated class can be interface, abstract, or a regular class
- Inheritance is used, but only for type matching if its an abstract or regular class
- New behavior is gained through composition, not inheritance.
- New behavior can be added before, or after in decorated objects methods.
Usage¶
- Useful when you need to add functionality to another class or object but you can’t, or don’t want to, modify the code of the existing object.
- When you need an object where functionality needs to be added or removed whimsically (licensed versus unlicensed features, perhaps!).
- To avoid subclass explosion if a large number of independent features need to be supported and sub-classing to support every combination would lead to class explosion.
Real World Usages¶
- java.io package uses decorators to decorate streams of data. Book example, ZipInputStream(BufferedInputStream(FileInputStream))
- FileInputStream, StringBufferInputStream, ByteArrayInputStream are the concrete components of the Inputstream interface.
- ZipInputStream, BufferedInputStream are the concrete decorators of the FilterInputStream, which is the component decorator.
- Adding authentication and authorization to a method or object is a great use for a decorator.
- Adding encryption and decryption to existing code
- Adding logging/auditing to existing code
- Adding a testing framework to existing code for pre and post conditions.
- Map/Reduce decorators to map and reduce a stream of input for data analytics.
Application to my Real World Application¶
Java Code Example¶
Main Take-Aways from the textbook¶
- Inheritance is usually NOT the best way to extend design.
- Build code that can be expanded, but without modifying existing code.
- Composition and delegation is a great way to add new runtime behavior.
- Avoid subclass explosion with the Decorator Pattern when you have many new features you need to add.
- Because decorators implement or inherit the base type, you can wrap as many as you want around each-other.
- Overuse of decorators can make code more cumbersome.
Main OOP Principles of Observer Pattern¶
- Open-Closed Principle
- Open for extension and closed for modification.