Decorator Pattern

  • aka Wrapper (Adapter Pattern is also known as Wrapper)
  • based on aggregation or composition
  • It lets you dynamically change the behavior of an object at run time by wrapping them in an object of a decorator class.
  • Examples:
    • java.util.Collections.unmodifiableList(List)
      • convert list to unmodifiable list
      • the methods that would change the list throw an UnsupportedOperationException
    • java.util.Collections.synchronizedList(List)
      • access to the list elements are synchronized and not accessible via multiple threads simultaneously.
    • java.io.BufferedReader(FileReader)
  • General Syntax:
var a = new Component();
var b = new Decorator1(a);
var c = new Decorator2(b);
c.execute();

Implementation

interface Giant {
    void attack();
    int getAttackPower();
}
 
class SimpleGiant implements Giant {
 
    @Override
    public void attack() {
        System.out.println("The giant tries to grab you!");
    }
 
    @Override
    public int getAttackPower() {
        return 10;
    }
}
 
class GiantAxeDecorator implements Giant {
    private final Giant decorated;
 
    public GiantAxeDecorator(Giant decorated) {
        this.decorated = decorated;
    }
 
    @Override
    public void attack() {
        decorated.attack();
        System.out.println("The giant swings at you with an axe!");
    }
 
    @Override
    public int getAttackPower() {
        return decorated.getAttackPower() + 10;
    }
}
  • Driver
public class Test {
    public static void main(String[] args) {
        var giant = new SimpleGiant();
        var giantWithAxe = new GiantAxeDecorator(giant);
        giantWithAxe.attack();
        // The giant tries to grab you!  
        // The giant swings at you with an axe!
        System.out.println(giantWithAxe.getAttackPower());
        // 20
    }
}

UML

Decorator_Pattern_UML