Decorator pattern

A decorator extends base object by modifying its behaviour. Each decorator contains a base object type reference, and at the same time is of base object type. That way, decorators can be chained one over another, and none of them know, if the reference base object they contain is in fact a concrete base object or just another decorator.

Sounds complicated? Let’s consider this example. A HotChocolate is a base object of type Beverage. A marshmallow can be added to the chocolate. A marshmallow is of type AddOn, which at the same time extends Beverage. An AddOn can take Beverage as a constructor parameter. So Marshmallow can take HotChocolate as a constructor parameter. So we have Marshmallow decorated HotChocolate.

Now, we have another AddOn – Sprinkles. Sprinkles can take HotChocolate as a constructor parameter. But, Sprinkles can also take Marshmallow decorated HotChocolate as a constructor parameter, without even knowing, that the input is not a concrete Beverage, but an AddOn which wraps around a Beverage!

Neat, isn’t it? The chain can continue, it can even has several decorator of the same kind (more marshmallows!).

Let’s look at the example of decorator pattern:

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

public class HotChocolate extends Beverage {
    @Override
    public int cost() { return 10; }
}

public abstract class AddOn extends Beverage{
}

public class Marshmellow extends AddOn {
    private final Beverage beverage;

    public Marshmellow(Beverage beverage) { this.beverage = beverage; }

    @Override
    public int cost() { return beverage.cost() + 1; }
}

public class Sprinkles extends AddOn {
    private final Beverage beverage;

    public Sprinkles(Beverage beverage) { this.beverage = beverage; }

    @Override
    public int cost() { return beverage.cost() + 5; }
}

Important things to keep in mind for Decorator Pattern:

  • Decorator and decorated are tied by common interfaces
  • Decorator has a referenced to the decorated object, being it concrete object or just another decorator
  • When decorating a method, decorator calls the decorated object method and adds its own behaviour (beverage.cost() + 5)

A huge thank you to Christopher Okhravi for his series on design patters. His video on Decorator Pattern has inspired me to write this post: https://www.youtube.com/watch?v=GCraGHx6gso&t=2882s

 

https://www.chabad.org/library/article_cdo/aid/2840060/jewish/Decadent-Hot-Cocoa-with-Marshmallows.htm