Decorator Design Pattern – Structural Patterns in Java

The Decorator Design Pattern is a special type of pattern one of the Structural Patterns, that allows you to add and removing behaviours to an individual object at the run-time dynamically or statically without changing the existing behaviour of other associated objects from the same class.

In software engineering, the common intent of all GOF structural patterns is to simplify the complex relationship between objects and classes in a flexible in the enterprise application. This Decorator pattern does this without violating the Single Responsibility Principle of the SOLID principle of object-oriented programming.

Decorator Design Pattern

According to the Gang of Four:

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

This design pattern uses the compositions over the inheritance for objects associations, it allows you to divide the functionality into different concrete classes with a unique area of concern.

Spring 5 Design Pattern Book

You could purchase my Spring 5 book that is with title name “Spring 5 Design Patterns“. This book is available on the Amazon and Packt publisher website. Learn various design patterns and best practices in Spring 5 and use them to solve common design problems. You could use author discount to purchase this book by using code- “AUTHDIS40“.
Spring-5-Design-Pattern

Applicability

There is a requirement of the business or might be some future planning for the product to extend behaviour by adding the new functionality to an object, to achieving it you could use inheritance to extend the behaviour of an object. But inheritance should be done at compile time and is also available for other instances of that class. And because of code modification required in case of inheritance, which is a violation of the Open Closed Principle. Instead, to avoid this violation of SOLID principle, you can attach new responsibility to an object dynamically. This is exactly the situation, the decorator design pattern comes into the picture and addresses this issue in a very flexible way.

UML Structure for Decorator Design Pattern

Let’s see the following figure that illustrates the classes and objects participating in this pattern are:

Decorator Design pattern
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 Component’s interface.

ConcreteDecorator (SeniorCitizen, Privilege)

  • It is a concrete implementation of Decorator and it adds responsibilities to the component.

Pros of the Decorator Pattern

There are following pros of using this decorator pattern.

  • This pattern allows you to extend functionality dynamically and statically without altering the structure of existing objects.
  • By using this pattern, you could add a new responsibility to an object dynamically.
  • Decorator pattern is also known as Wrapper.
  • It uses the compositions for object relationships to maintain SOLID principles.
  • By using this pattern we can simplify coding by writing new classes for every new specific functionality rather changes into the existing code of your application.

Cons of the Decorator Pattern

There are following pros of using this decorator pattern.

  • Decorator pattern can result in many small objects in our design, and overuse can be complex
  • It can cause issues if the client relies heavily on the components concrete type
  • Decorators can complicate the process of instantiating the component because you not only have to instantiate the component but wrap it in a number of decorators

Real Case Study for the Decorator Design Pattern

Let’s look into the following example how to implement this design pattern into a real case study.

Consider a Bank offers multiple accounts with different benefits to the customers, it divided the customers into three categories as like Senior Citizen, Privilege and Young. Bank launched a scheme to the Saving account for Senior citizen as bank provides a medical insurance of up to $1,000 for Senior Citizen if they open saving account in this bank, similarly bank also provides a scheme to the privilege 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 how our design looks like now. Clearly, this design is flawed, but this is an ideal use case for the decorator pattern. Decorator design pattern allows you to add run time dynamically behaviour, in this case, I will create an abstract AccountDecorator class to implement Account. And furthermore, I will create the SeniorCitizen and Privilege class extend and AccountDecorator because Young does not have any extra benefits, so class SavingClass does not extend AccountDecorator. This is how the design will be.

design with decorator pattern

In the figure above, it follows the Decorator Design Pattern by creating AccountDecorator as a Decorator in this pattern, and focus on the important thing to observe the relationship between Account and AccountDecorator. This relationship as below:

  • IS-A relationship between the AccountDecorator and Account, i.e. inheritance for the correct type.
  • HAS-A relationship between the AccountDecorator and Account, the i.e. composition in order to add new behaviour without changing existing code.

Sample Implementation of the Decorator Design Pattern

Let’s look into the following sample codes to demonstrate the Decorator Design Pattern.

Step 1: Create an interface.

Account.java

package com.doj.patterns.structural.decorator;

public interface Account {
	String getTotalBenefits();
}

Step 2: Create concrete classes implementing the same interface.

SavingAccount.java

package com.doj.patterns.structural.decorator;

/**
 * @author Dinesh.Rajput
 *
 */
public class SavingAccount implements Account {

	@Override
	public String getTotalBenefits() {
		return "This account has 4% interest rate with per day $5000 withdrwal limit";
	}

}

CurrentAccount.java

package com.doj.patterns.structural.decorator;

/**
 * @author Dinesh.Rajput
 *
 */
public class CurrentAccount implements Account{
	
	@Override
	public String getTotalBenefits() {
		return "There is no withdrwal limit for current account";
	}

}

Step 3: Create abstract decorator class implementing the Account interface.

AccountDecorator.java

package com.doj.patterns.structural.decorator;

/**
 * @author Dinesh.Rajput
 *
 */
public abstract class AccountDecorator implements Account{
	
	abstract String applyOtherBenefits();

}

Step 4: Create a concrete decorator class extending the AccountDecorator class.

Privilege.java

package com.doj.patterns.structural.decorator;

/**
 * @author Dinesh.Rajput
 *
 */
public class Privilege extends AccountDecorator {
	
	Account account;
	
	public Privilege(Account account) {
		super();
		this.account = account;
	}

	@Override
	public String getTotalBenefits() {
		return account.getTotalBenefits() + " other benefits are "+applyOtherBenefits();
	}

	@Override
	String applyOtherBenefits() {
		return " an accident insurance of up to $1,600 and an overdraft facility of $84";
	}

}

Step 5: Let’s create a demo class and use the Privilege to decorate Account objects.

DecoratorPatternMain.java

package com.doj.patterns.structural.decorator;

/**
 * @author Dinesh.Rajput
 *
 */
public class DecoratorPatternMain {

	public static void main(String[] args) {
		/*Saving account with no decoration*/
		Account basicSavingAccount = new SavingAccount();
		System.out.println(basicSavingAccount.getTotalBenefits());
		
		/*Saving account with senior citizen benefits decoration*/
		Account seniorCitizenSavingAccount = new SavingAccount();
		seniorCitizenSavingAccount = new SeniorCitizen(seniorCitizenSavingAccount);
		System.out.println(seniorCitizenSavingAccount.getTotalBenefits());
		
		/*Saving account with privilege decoration*/
		Account privilegeCitizenSavingAccount = new SavingAccount();
		privilegeCitizenSavingAccount = new Privilege(privilegeCitizenSavingAccount);
		System.out.println(privilegeCitizenSavingAccount.getTotalBenefits());
	}

}

Step 6: Let’s run the above demo class and verify the output.

This account has 4% interest rate with per day $5000 withdrwal limit
This account has 4% interest rate with per day $5000 withdrwal limit other benefits are  an medical insurance of up to $1,000 for Senior Citizen
This account has 4% interest rate with per day $5000 withdrwal limit other benefits are  an accident insurance of up to $1,600 and an overdraft facility of $84

Examples of the Decorator Design Pattern in Java API

There are following implementations of this pattern.

  • java.io.BufferedReader;
  • java.io.FileReader;
  • java.io.Reader;
Previous
Next

One Response

  1. muniswamy setty k s December 26, 2018