[Head First Design Patterns] Decorators Pattern
09 Apr 2022The decorator pattern
Design principles
Classes should be open for extension, but closed for modification
Def
- decorating objects
- Figure shows decorators objects
Mocha, Whip
wrap and decorateconcrete Beverage (DarkRoast)
component
- it has a
same supertype
as the object they decorate the decorators adds its own behavior
before/after delegating to the object it decorates to do the rest of the job- objects can be decorated at any time, so we can
decorate object dynamically at runtime
with as many decorators as we like
Implementation
-
Brief implementation flow: 1) Implement concrete classes for
Beverage
abtract class / interface, ie.DarkRoast, Juice
2) Define decorators which will be able to wrap and extend new behaviors to concreteBeverage
classes +By inheriting Beverage
, create abstract class for beverage condimentsBeverageCondiment
which to follow the same type which the superclassBeverage
+ Bycomposing Beverage
in condiments abtract class, it will allow us to add any new behaviors to the condiment decorators at runtime 3) Implement condiment decorators (Mocha, Ship, Soy
) which extended from abtract classBeverageCondiment
4) Now the decorators ready to wrap any Beverage objects to extend new behaviors - Notes: (confusion over
Inheritance
versusComposition
)- using inheritance ->
type matching
(not toget behaviors
) - acquiring new behavior by composing objects together
- why we need
type matching
? We need thesame interface
as the component because they need to stand in place of the component
- using inheritance ->
-
if we rely on
inheritance
, our behaviour can only be determined staticallyat compile time
.With composition
, we can mix and match decorators any way we likeat runtime
Java I/O decorators
- An example of builtin Java I/O decorator
- concrete components implements
InputStream
interface and implemented concrete decorators follow the same type