This is one of the structural design patterns. This pattern acts as a wrapper to the existing class. The Decorator pattern lets us attach additional responsibilities and modify an instance functionality dynamically without affecting the original object or other objects. Decorators provide a flexible alternative to subclassing for extending functionality, using composition instead of inheritance.
Class Diagram
Implementation
Create an Interface
package com.roytuts.designpattern.decorator; public interface Pizza { String size(); String ingredients(); }
Create an implementation class – VegPizza
package com.roytuts.designpattern.decorator; public class VegPizza implements Pizza { @Override public String size() { return "Medium"; } @Override public String ingredients() { return "Vegetables"; } }
Create an another implementation class – NonVegPizza
package com.roytuts.designpattern.decorator; public class NonVegPizza implements Pizza { @Override public String size() { return "Big"; } @Override public String ingredients() { return "Mutton"; } }
Create an abstract class – SubstanceDecorator
package com.roytuts.designpattern.decorator; public abstract class SubstanceDecorator implements Pizza { protected Pizza decoratedPizza; public SubstanceDecorator(Pizza decoratedPizza) { this.decoratedPizza = decoratedPizza; } public String size() { return decoratedPizza.size(); } public String ingredients() { return decoratedPizza.ingredients(); } }
Create a concrete class – ChickenDecorator
package com.roytuts.designpattern.decorator; public class ChickenDecorator extends SubstanceDecorator { public ChickenDecorator(Pizza decoratedPizza) { super(decoratedPizza); } @Override public String ingredients() { return decoratedPizza.ingredients() + " and " + addChicken(); } private String addChicken() { return "Add Chicken to Pizza"; } }
Create another concrete class – CheeseDecorator
package com.roytuts.designpattern.decorator; public class CheeseDecorator extends SubstanceDecorator { public CheeseDecorator(Pizza decoratedPizza) { super(decoratedPizza); } @Override public String ingredients() { return decoratedPizza.ingredients() + " and " + addCheese(); } private String addCheese() { return "Add Cheese to Pizza"; } }
Create a test class for testing the Decorator Pattern
package com.roytuts.designpattern.decorator; public class DecoratorPatternTest { /** * @param args */ public static void main(String[] args) { Pizza vegPizza = new VegPizza(); Pizza nonVegPizza = new NonVegPizza(); SubstanceDecorator cheesePizza = new CheeseDecorator(new VegPizza()); SubstanceDecorator chickenPizza = new ChickenDecorator(new NonVegPizza()); System.out.println("Normal Veg Pizza"); System.out.println("size: " + vegPizza.size()); System.out.println("ingredients: " + vegPizza.ingredients()); System.out.println(); System.out.println("Normal Non Veg Pizza"); System.out.println("size: " + nonVegPizza.size()); System.out.println("ingredients: " + nonVegPizza.ingredients()); System.out.println(); System.out.println("Veg Pizza after adding Cheese"); System.out.println("size: " + cheesePizza.size()); System.out.println("ingredients: " + cheesePizza.ingredients()); System.out.println(); System.out.println("Non Veg Pizza after adding Chicken"); System.out.println("size: " + chickenPizza.size()); System.out.println("ingredients: " + chickenPizza.ingredients()); System.out.println(); } }
Run the above class. You will see the below output in the console.
Output
Normal Veg Pizza size: Medium ingredients: Vegetables Normal Non Veg Pizza size: Big ingredients: Mutton Veg Pizza after adding Cheese size: Medium ingredients: Vegetables and Add Cheese to Pizza Non Veg Pizza after adding Chicken size: Big ingredients: Mutton and Add Chicken to Pizza
That’s all. Thank you for your reading.