The Decorator Design Pattern

The Decorator Design Pattern


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.

Basic structure of the Decorator Design Pattern

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. 

ISalaryService Interface and SalaryService class

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.

No alt text provided for this image

Let's look at the existing code of the ISalaryService and SalaryService classes.

ISalaryService Interface

No alt text provided for this image

SalaryService

No alt text provided for this image

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.

No alt text provided for this image

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.

No alt text provided for this image

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.

No alt text provided for this image

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.

No alt text provided for this image

In the 12th line, when we are creating the SalaryService, it needs to be wrapped in our ‘SalaryServiceBonusDecorator’ as follows.

No alt text provided for this image

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. 



Rashan Liyanage

Senior Software Engineer @ Amused Group Lanka (PVT) LTD .Net | Azure

4 年

Great work Darshana Edirisinghe ayye

Laksith Liyanage

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.

Sasanga Edirisinghe

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.

要查看或添加评论,请登录

社区洞察

其他会员也浏览了