The Decorator Design Pattern
Darshana Edirisinghe
Tech Visionary and Problem Solver | Leading Teams to Success
What is the Decorator Pattern?
Decorator / A structural design pattern used for dynamically adding behaviors to the class Without making changes to that class. This helps to create strong separations of concerns in the code base and also add, Remove, and resequencing the behaviors as needed.
You will get a better idea about the decorator pattern while reading this article. Let’s look at the below chart to get the basic idea.
Let’s say, we have a class and it has some functionalities. We need to add additional functionalities to that class without breaking the SOLID principles. Therefore, we can use this Decorator pattern to add those additional functionalities to that class.
How do we use it?
Example: Add additional functionalities to the Salary Calculator
Let’s say, we have a service class to calculate the salary called ‘SalaryService’ Class. That class has two functions ‘CalculateMonthlyBasisSalary ()’ and ‘CalculateHourlySalary ()’. Then, there is a new requirement came, to add work from home bonus to the salary to appreciate the effort of the employees.
If we add the bonus calculations into the SalaryService Class, it makes it harder to read the code, and it also makes it harder to understand what exactly this SalaryService class is for. And also, there is a possibility to introduce new errors or bugs to the SalaryService class. This is also allowed to ‘one class handles multiple concerns’ that break the single responsibility principle.
Therefore, we are going to create a ‘SalaryServiceBonusDecorator’ to add the bonus amount to the fix and an hourly rate salary and calculate the net salary. And that will make each and every class focused on a single concern.
Let's look at the existing code of the ISalaryService and SalaryService classes.
ISalaryService Interface
SalaryService
I’m going to add a decorator called SalaryServiceBonusDecorator. Therefore, I can apply this decorator class to any implementation that implements the ‘ISalaryService’ interface. This decorator class is based on the abstraction of ISalaryService, not any particular concrete implementation.
Creating a decorator class
The first thing we need to do is, Decorator needs to implement the same interface or extend the same base class as the classes that it will be decorating.
Then, It needs to take an instance of the class to be decorated -> ISalaryService object. So, I’m going to create a member variable called SalaryService. Using this way, we can implement the decorator as follows.
We haven’t added any additional functionalities yet as per the requirement at this point. Please make sure to provide the least implementation for every method, otherwise, this won’t work. Let’s add additional functionality as required.
Here I get the bonus value from ‘bonusCalculator’ class and add this value to the ‘grossSalary’ and return the ‘netSalary’. Using this pattern, we can add additional functionalities around the SalaryService functions. We can change the parameters of the SalaryService functions, we can change the return values by adding the additional functions to the decorator class.
Tell the application we need to use the decorator
Implementation is not finished yet. We need to tell our application, that we want to use this decorator. To implement that we can add some modifications to the Home Controller.
This is the ‘HomeController’ before we do the modifications.
In the 12th line, when we are creating the SalaryService, it needs to be wrapped in our ‘SalaryServiceBonusDecorator’ as follows.
So now we have our concrete SalaryService wrapped in our SalaryServiceBonusDecorator. When we debug the code, we can see the calls first pass through the decorator object before they go to the SalaryService object.
Where to use the Decorator pattern?
Use cases like,
- Logging.
- Performance tracking.
- Caching.
- Authorization.
Modify the data that is sent to or from a component
- When we need to encrypt or decrypt an object before being passed to a component.
- When there are some fields whose values need to convert.
Senior Software Engineer @ Amused Group Lanka (PVT) LTD .Net | Azure
4 年Great work Darshana Edirisinghe ayye
Technical Lead Engineer at Pearson
4 年Excellent way of teaching a new concept with a simple touch to understand it very clear. Very useful document and thank you so much for sharing this concept to enhance our knowledge. Well aligned and clearly articulated.
Tech Lead | Consultant | Dev
4 年This article is very helpful as it explains decorator pattern from the very beginning. Thank you so much for guiding through this design pattern from the most simplest point to advanced points. Keep it up.