Problem
You want to add behavior or state to individual objects at run-time. Inheritance is not feasible because it is static and applies to an entire class.
What is the Decorator Pattern?
The Decorator Pattern attaches additional responsibilities to an object statically or dynamically. A Decorator provides an enhanced interface to the original object. In the implementation of this pattern, we prefer composition over an inheritance – so that we can reduce the overhead of subclassing again and again for each decorating element. The recursion involved with this design can be used to decorate our object as many times as we require.
The ornaments that are added to pine or fir trees are examples of Decorators. Lights, garland, candy canes, glass ornaments, etc., can be added to a tree to give it a festive look. The ornaments do not change the tree itself which is recognizable as a Christmas tree regardless of particular ornaments used. As an example of additional functionality, the addition of lights allows one to “light up” a Christmas tree.
Another example: an assault gun is a deadly weapon on its own. But you can apply certain “decorations” to make it more accurate, silent and devastating.
Purpose
How to implement
Example
public interface Weapon { boolean aimAndFire(); } public class Gun implements Weapon { @Override public boolean aimAndFire() { System.out.println("fire gun!!!"); return true; } } public class AK47 extends WeaponDecorator { public AK47(Weapon weapon) { super(weapon); } @Override public boolean aimAndFire() { // TODO Auto-generated method stub super.aimAndFire(); // add additional functionalities. System.out.println("It's an AK47, fire 5 rounds a pull!"); return true; } } public class Automatic extends WeaponDecorator { public Automatic(Weapon weapon) { super(weapon); } @Override public boolean aimAndFire() { super.aimAndFire(); // add additional functionalities. System.out.println("It's an automatic, put on silencer and fire 10 rounds a pull!"); return true; } } public class SniperRiffle extends WeaponDecorator { public SniperRiffle(Weapon weapon) { super(weapon); } @Override public boolean aimAndFire() { // TODO Auto-generated method stub super.aimAndFire(); // add additional functionalities. System.out.println("It's a SniperRiffle, put on scope and fire 1 round a pull!"); return true; } }
public class DecoratorDemo { public static void main(String[] args) { // TODO Auto-generated method stub Weapon ak47 = new AK47(new Gun()); System.out.println("fired ak47: " + ak47.aimAndFire()); System.out.println(); Weapon automatic = new Automatic(new Gun()); System.out.println("fired automatic: " + automatic.aimAndFire()); System.out.println(); // here a riffle can fire like a riffle and also as a automatic(or other guns) Weapon riffle = new SniperRiffle(new Automatic(new Gun())); System.out.println("fired riffle: " + riffle.aimAndFire()); System.out.println(); List<Weapon> weapons = Arrays.asList(new AK47(new Gun()), new Automatic(new Gun()), new SniperRiffle(new Gun())); weapons.stream().forEach(weapon -> { System.out.println("fire weapon: " + weapon.aimAndFire()); System.out.println(); }); } }
Results
fire gun!!! It's an AK47, fire 5 rounds a pull! fired ak47: true fire gun!!! It's an automatic, put on silencer and fire 10 rounds a pull! fired automatic: true fire gun!!! It's an automatic, put on silencer and fire 10 rounds a pull! It's a SniperRiffle, put on scope and fire 1 round a pull! fired riffle: true fire gun!!! It's an AK47, fire 5 rounds a pull! fire weapon: true fire gun!!! It's an automatic, put on silencer and fire 10 rounds a pull! fire weapon: true fire gun!!! It's a SniperRiffle, put on scope and fire 1 round a pull! fire weapon: true
Uses
Advantages
Disadvantages