Let’s imagine we want to create a game, and for our superhero, we want to add a new gadget to every level of the game and gadget should be selected by the player.
How we can do that?🤔
One way to do that use traditional inheritance, We will create a base abstract gadget class and multiple subclasses for different gadget combination.
But wait I have n numbers of gadgets so in my case I have to create n! subclasses.
If n = 5 then for 5 powers the number of subclasses will be 5! = 120. For 5 gadget we have to create 120 subclasses.😢
Is there any other simple way to do that?
Yes, We can use Decorator Design Pattern to solve this problem.
Decorator Design Pattern allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class
Decorator Design Pattern comes under structural pattern. This pattern creates a decorator class which wraps the original class and provides additional functionality keeping class methods signature intact.
We will create a Gadget interface and concrete classes implementing the Gadget interface. We will then create an abstract decorator class GadgateDecorator implementing the Gadget interface and having Gadget object as its instance variable.
FlightGadget and UnibeamChestProjectorGadget are concrete classes implementing GadgateDecorator.
Suit class will implement Gadget interface and it will be our base gadget or first gadget.
Gadget.java
1 2 3 4 5 6 |
package com.genericclass.decorator.design.pattern; public interface Gadget { Gadget addGadget(); void showGadget(); } |
GadgetDecorator.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.genericclass.decorator.design.pattern; public abstract class GadgetDecorator implements Gadget{ Gadget nextGadget; public GadgetDecorator(Gadget nextGadget) { this.nextGadget = nextGadget; } @Override public Gadget addGadget() { return this; } @Override public void showGadget() { nextGadget.showGadget(); } } |
FlightGadget.java
1 2 3 4 5 6 7 8 9 10 11 |
package com.genericclass.decorator.design.pattern; public class FlightGadget extends GadgetDecorator { public FlightGadget(Gadget nextGadget) { super(nextGadget); } @Override public void showGadget() { super.showGadget(); System.out.println(" Flying Gadget..."); } } |
UnibeamChestProjectorGadget.java
1 2 3 4 5 6 7 8 9 10 11 |
package com.genericclass.decorator.design.pattern; public class UnibeamChestProjectorGadget extends GadgetDecorator { public UnibeamChestProjectorGadget(Gadget nextGadget) { super(nextGadget); } @Override public void showGadget() { super.showGadget(); System.out.println(" Unibeam Chest Projector..."); } } |
Suit.java
1 2 3 4 5 6 7 8 9 10 |
package com.genericclass.decorator.design.pattern; public class Suit implements Gadget{ @Override public Gadget addGadget() { return this; } @Override public void showGadget() { System.out.println(" Iron Man Suit..."); } } |
IronMan.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.genericclass.decorator.design.pattern; public class IronMan { Gadget gadget = new Suit(); public void addNewGadget(String gadgetName) { if(gadgetName.equals("Flight")) this.gadget = new FlightGadget(gadget); else this.gadget = new UnibeamChestProjectorGadget(gadget); } public void showGadget() { System.out.println("My Gadgets:"); gadget.showGadget(); } } |
Main.java
1 2 3 4 5 6 7 8 |
package com.genericclass.decorator.design.pattern; public class Main { public static void main(String[] args) { IronMan ironMan = new IronMan(); ironMan.addNewGadget("Unibeam Chest Projector"); ironMan.addNewGadget("Flight"); ironMan.showGadget(); } } |
Output:
1 2 3 4 |
My Gadgets: Iron Man Suit... Unibeam Chest Projector... Flying Gadget... |
Decorator Pattern provides greater flexibility than static inheritance. It enhances the extensibility of the object because changes are made by coding new classes.
Decorator Pattern can be used when we want to add responsibilities dynamically at runtime.