Decorator Pattern Java(System Design)

Kaushik Ghosh
2 min readMar 12, 2024

--

Suppose you have a class.It have some responsibilities and it can be decorated by adding some decoration. In that case Decorator Pattern need.

Assume an example,

Like I have a Ice-cream.I need Mango Flavour with Vanilla Flavour.

The total price will different with adding that flavour cost also right.

Therefore,Decorator Design Pattern also same like that

Basically a class(IceCream) is extensible but not modifiable.So that class extends a main (Flavour)decorator Class .That Decorator class will be extensible to their sub/child (Lichi/Mango/Vanilla)class.

Let’s understand the Decorator Pattern

  • Component(Ex: IceCream): The Component defines the interface for any objects that have some responsibilities and can be added dynamically
  • ConcreteComponent(Ex: CupIceCream/ConeIceCream): It is simply an implementation of Component interface
  • Decorator(Ex: ToppingsDecorator): The Decorator has a reference to a Component, and also conforms to the Component interface. Decorator is essentially wrapping the Component
  • ConcreteDecorator(VanillaFlavour/MangoFlavour): The ConcreteDecorator just adds responsibilities to the original Component.

BaseIceCream.java

package IceCreams;

public abstract class BaseIceCream {
public abstract int cost();
}

ConeIceCream.java

package IceCreams;

public class ConeIceCream extends BaseIceCream {
@Override
public int cost() {
return 45;
}
}

ToppingsDecorator.java

package Flavours;

import IceCreams.BaseIceCream;

public abstract class ToppingsDecorator extends BaseIceCream {

}

LichiFlavour.java

package Flavours;

import IceCreams.BaseIceCream;

public class LichiFlavour extends ToppingsDecorator{
BaseIceCream iceCream;
public LichiFlavour(BaseIceCream iceCream){
this.iceCream = iceCream;
}

@Override
public int cost(){
return 25+iceCream.cost();
}
}

MangoFlavour.java

package Flavours;

import IceCreams.BaseIceCream;

public class MangoFlavour extends ToppingsDecorator{
BaseIceCream iceCream;
public MangoFlavour(BaseIceCream iceCream){
this.iceCream = iceCream;
}

@Override
public int cost(){
return 20+iceCream.cost();
}

}

VanillaFlavour.java

package Flavours;

import IceCreams.BaseIceCream;

public class VanillaFlavour extends ToppingsDecorator {
BaseIceCream iceCream;
public VanillaFlavour(BaseIceCream iceCream){
this.iceCream = iceCream;
}

@Override
public int cost(){
return 30+iceCream.cost();
}
}

Main.java

import IceCreams.BaseIceCream;
import IceCreams.ConeIceCream;
import Flavours.LichiFlavour;
import Flavours.MangoFlavour;
import Flavours.VanillaFlavour;

public class Main {
public static void main(String[] args) {

BaseIceCream iceCream1 = new MangoFlavour(new LichiFlavour(new ConeIceCream()));
System.out.println("Cost of IceCream is: "+iceCream1.cost());
BaseIceCream iceCream2 = new LichiFlavour(new VanillaFlavour(new ConeIceCream()));
System.out.println("Cost of IceCream is: "+iceCream2.cost());

}
}

Output:

Use cases of Decorator Design Pattern:

  1. Car Design
  2. Pizza Decoration
  3. Coffee base System Decoration

--

--

Kaushik Ghosh
Kaushik Ghosh

Written by Kaushik Ghosh

Software Engineer,Java Developer

Responses (1)