Design Patterns - Decorator Pattern
19 Oct 2017Decorator Pattern is a design pattern that allows behavior to be added to an individual objects without affecting the behavior of other objects from the same class.
Intent
According to Gang of Four, the intent of Decorator Patterns is to:
Attach additional responsibility to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
Problem
You want to add behavior or state to individual objects at run-time.
Solution
Allows for extending the functionality of an object without sub-classing for extending functionality.
Participants
- Component Interface - The
interface
orabstract
defining the function added to it by the Decorator. - Concrete Component - Basic implementation of the Component Interface.
- Decorator - Decorator class implements the Component Interface and it has a HAS-A relationship with the Component Interface. In other words, Decorator class wraps the Component class.
- Concrete Decorator - Extends the base decorator functionality and modifying the component behavior accordingly.
Implementation
Create an abstract class that represents both the original class and the new functions to be added to the class. In the decorators, place the new function class before or after the trailing class to get the correct order.
Example
Component Interface
Car.java
package com.art.designpatterns.decorator;
/*
Component Interface - Defines Interface for all the Classes to Use
*/
public interface Car {
void assemble();
}
Component Implementation
HondaCar.java
package com.art.designpatterns.decorator;
/**
* Concrete Component - Class having function added to it
*/
public class HondaCar implements Car{
@Override
public void assemble() {
System.out.println("Assembling Honda Car");
}
}
Decorator
CarDecorator.java
package com.art.designpatterns.decorator;
/**
* Decorator Class
*/
public class CarDecorator implements Car{
protected Car car;
public CarDecorator(Car car) {
this.car = car;
}
@Override
public void assemble() {
this.car.assemble();
}
}
Concrete Decorators
LuxuryFeature.java
package com.art.designpatterns.decorator;
/**
* Concrete Decorator with Added Behaviour
*/
public class LuxuryFeature extends CarDecorator{
public LuxuryFeature(Car car) {
super(car);
}
@Override
public void assemble() {
super.assemble();
System.out.println("Adding Features of Luxury Car");
}
}
SportsFeature.java
package com.art.designpatterns.decorator;
/**
* Concrete Decorator with Added Behaviour
*/
public class SportsFeature extends CarDecorator{
public SportsFeature(Car car) {
super(car);
}
@Override
public void assemble() {
super.assemble();
System.out.println("Adding Features of Sports Car");
}
}
Demo
package com.art.designpatterns.decorator;
public class DecoratorDesignPatternDemo {
/**
* Demo of Decorator Design pattern where Decorator's are added to Concrete Class
* HondaCar is Concrete Component
* LuxuryCar or SportsCar based on Abstract Decorator Class
* @param args
*/
public static void main(String[] args) {
Car sportCar = buildSportsHondaCar();
sportCar.assemble();
Car luxuryCar = buildLuxuryHondaCar();
luxuryCar.assemble();
}
private static Car buildSportsHondaCar() {
Car baseCar1 = new HondaCar();
Car sportCar = new SportsFeature(baseCar1);
return sportCar;
}
private static Car buildLuxuryHondaCar() {
Car baseCar2 = new HondaCar();
Car luxuryCar = new LuxuryFeature(baseCar2);
return luxuryCar;
}
}
Summary
-
It is also known as Wrapper Pattern as it allows behavior to be added to an individual objects either statically or dynamically without affecting the behavior of other objects from the same class.
-
Decorator pattern allows to create a chain of objects that starts with the Decorator Object - the objects responsible for the new function and ends with the concrete Component.
-
Adheres to Open Close Principle
Tweet Follow @aayushtuladharClasses should be open for extension, but closed for modification.