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 adding and removing behaviors to an individual object at the run-time dynamically or statically without changing the existing behavior of other associated objects from 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 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 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 behavior by adding the new functionality to an object, to achieving it you could use inheritance to extend the behavior of an object. But inheritance should be done at compile time and it 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 picture and addresses this issue in 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 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 extending functionality dynamically and statically without altering the structure existing objects.
  • By using this pattern, you could add new responsibility to an object dynamically.
  • Decorator pattern is also know 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 functionalities 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 following example how to implement this design pattern into 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 an 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 are no scheme for the Young.

To address the new requirement, we can add new sub classes of SavingAccount, one each to represent a saving account with an 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 adding run time dynamically behavior, in this case, I will create an abstract AccountDecorator class to implement Account. And further more, 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 important thing to observe the relationship between Account and AccountDecorator. These relationship as below:

  • IS-A relationship between the AccountDecorator and Account, i.e. inheritance for correct type.
  • HAS-A relationship between the AccountDecorator and Account, i.e. composition in order to add new behavior 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 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;