Decorator
Updated: 03 September 2023
“Decorator is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors”
The decorator pattern is about changing the behaviour of a method at runtime instead of compile time. This allows us to modify functionality of a class without modifying the class contents
To do this we wrap the component object in a decorator object
A decorator has the exact same interface/abstract class as the component object (the component) therefore making it exchangable with the component object
“The decorator pattern attaches additional responsibilities to an object dynamically (at runtime). Decorators provide a flexible alternative to subclassing, allows the use of composition to share behaviour”
The decorator inherits from the component and also has a property of type component
The functioning of the decorator pattern makes use of recursion
Example
We could implement a multi-factor authentication type model by using the decorator pattern using something like the following:
Base Classes
Before we can create our concrete implementations we need to establish the base classes for our Logins and Decorators to work from, we can simply create two classes in which our AbstractLogin
is the main root, and our LoginDecorator
inherits from AbstractLogin
Login Implementation
We can implement our login as any class that inherits from the Login
and carries out a login functionality, like so:
Decorator Implementation
Lastly, we need to implement decorators such that each decorator will make some reference/call to the inner AbstractLogin
in order to carry out the login behaviour and extend on it’s behaviour
Since decorators can be wrapped arbitrarily we can add another decorator which is pretty much exactly the same as above:
Using the Decorator Pattern
Given the way we’ve configured our decorator each one takes an instance of AbstractLogin
in the constructor, this could be initialized in any method but this one is straightforward to use
We want to create an instance of the LocalUser
which has the ability to implement some kind of multi factor auth that needs both a successful email and SMS pin to be verified.
Implementing the decorator pattern with just the EmailPinLoginDecorator
would look like so:
Implementing this using the above classes looks like this:
Based on the way the decorator pattern works we could even make things more complicated by requiring more layers of decorators or can simplify the implementation by removing decorators as you can see above
The way the pattern works means there’s no limit to how many layers you are able to decorate with and allows for very complex implementation and abstraction when using this kind of pattern