- Spring 5 Design Patterns
- Dinesh Rajput
- 550字
- 2021-07-08 09:59:39
Common problems solved by the Decorator pattern
In an enterprise application, there is a business requirement or there might be a future plan to extend the behavior of the product by adding new functionalities. To achieve this, you could use inheritance to extend the behavior of an object. But inheritance should be done at compile time and methods are also available for other instances of that class. Because of the code modification, there is a violation of the Open Closed Principle. To avoid this violation of the SOLID principle, you can attach new responsibility to an object dynamically. This is the situation where the decorator design pattern comes into the picture and addresses this issue in a very flexible way. Let's look at the following example of how to implement this design pattern into a real case study.
Consider that a bank offers multiple accounts with different benefits to customers. It divides the customers into three categories--senior citizens, privileged, and young. The bank launches a scheme on the savings account for senior citizens--if they open a savings account in this bank, they will be provided medical insurance of up to $1,000. Similarly, the bank also provides a scheme for the privileged customers as an accident insurance of up to $1,600 and an overdraft facility of $84. There is no scheme for the young.
To address the new requirement, we can add new subclasses of SavingAccount; one each to represent a saving account with additional benefits as decoration, and this is what our design looks like now:
This design will be very complex as I will add more benefit schemes to the SavingAccount, but what would happen when the bank launches the same scheme for CurrentAccount? Clearly, this design is flawed, but this is an ideal use case for the decorator pattern. This pattern allows you to add runtime dynamic behavior. In this case, I will create an abstract AccountDecorator class to implement Account. And furthermore, I will create the SeniorCitizen class and Privilege class, which extends AccountDecorator because young does not have any extra benefits, so the SavingAccount class does not extend AccountDecorator. This is how the design will be:
The preceding figure follows the Decorator design pattern by creating AccountDecorator as a Decorator in this pattern, and focuses on important things to observe the relationship between Account and AccountDecorator. This relationship is as follows:
- Is-a relationship between the AccountDecorator and Account, that is, inheritance for the correct type
- Has-a relationship between the AccountDecorator and Account, that is, composition in order to add new behavior without changing the existing code
Let's look at the UML structure:
The classes and objects participating in this pattern are:
- Component (Account): It is an interface for objects that can have responsibilities added to them dynamically
- ConcreteComponent (SavingAccount): It is a concrete class of component interface and it defines an object to which additional responsibilities can be attached
- Decorator (AccountDecorator): It has a reference to a Component object and defines an interface that conforms to the interface of the component
- ConcreteDecorator (SeniorCitizen and Privilege): It is a concrete implementation of Decorator and it adds responsibilities to the component