Design Patterns: The Decorator Pattern

Earlier in this series we explored both the facade and adapter design patterns in this series. Using facade, we can simplify large systems, and by implementing adapter we can stay safe while working with external API and classes. Now we are going to cover the decorator design pattern, which also falls under the category of structural patterns.

We can use the decorator pattern when we just want to give some added responsibility to our base class. This design pattern is a great alternative to a sub‑classing feature for extending functionality with some added advantages.

The Problem

If you are confused and think that we can achieve the same functionality with a sub‑classing feature as well, then let me show you some code examples which will remove your confusion and make you love the decorator pattern.

I am going to take an example of a class which is responsible for generating content for an email. In the next code block, as you can see, this class functions very well for generating email content without any modification.

We know that Christmas is coming, and let's say I want to greet my reader with a message for my next newsletter email. So I have to add a message in my email body with an image which looks good. 

For this I can directly edit in my email class, which I really don't want to do. So I can implement inheritance to achieve the same effect. I create a separate child class of the main email body class:

So I am done with my code, and after a few days I want to send an email with New Year's greetings. We can use the same method as we did for Christmas.

This went smoothly without any more issues. Now let's say I forget to greet my visitors for both occasions (Christmas and New Year) and I want to send both greetings in one email, without modifying any code in the base class. 

Your mind gets filled immediately with the following question: Will sub-classes and inheritance help here? I would be in favor of going that way, but we will need to use extra/unnecessary code to achieve this. We can use traits which enable us to implement something similar to multiple inheritance.

The Solution

The problem which we have discussed in the previous section can be resolved by implementing the decorator pattern. 

According to Wikipedia:

The decorator pattern (also known as Wrapper, an alternative naming shared with the Adapter pattern) is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.

In the above section we have seen that we can extend features/behavior using one sub-class, but when it comes to adding multiple features/behaviors, it becomes lengthy and complex. And that's where we should use the decorator pattern.

Interface

This is a simple interface to make sure that some class must implement the required methods. 

Main Email Class

This is the main class which is generating the default body of an email, which I generally use to send emails. What I need, however, is to modify body content based on some occasion but without altering the main email class.

Main Decorator

This is our main decorator class, which holds the reference to our main email class and changes its behavior as needed. Here we have defined one abstract method, loadBody, which sub decorator needs to implement to change behavior.

Sub Decorator

Here we have created two sub-classes of the main decorator, which actually performs a change of behavior for our main email class.

Wrapping It All Together

We have created all required elements. All we need to do is use our code and enjoy.

Now we will use this decorator class in various ways as needed:

We can see that now we have altered the body of an email without modifying the main email class.

Conclusion

Every application we have needs some sort of alteration and/or improvements at uniform intervals. So in such a case we can implement the decorator design pattern and it will ultimately improve code quality and make our code more extendable.

This was my effort to explain you about the decorator pattern, but if you have additional comments or questions, please don't hesitate to add them in the feed below.

Tags:

Comments

Related Articles