Design Patterns: Decorator Pattern

·

4 min read

I am working my way through Head First Design Patterns and I will be sharing my notes on each topic. Design patterns are an important object oriented programming concept as they help software engineers have an arsenal of solutions to problems that show up often. I really want to hone in on and refine my craft as a software engineer so it makes sense to me to understand these concepts. I will share my journey along the way! I may even come up with an Anki deck of this book.

I owe a big thanks to Christopher Okhravi. Check out his YouTube series on the book here.

I will put keep all my notes on this notion page here so feel free to use that as a reference. The rest of this blog post will simply be a copy paste of the information there. If you feel that my notes are lacking or incorrect in some way, please let me know! I am open to criticism.

My TL;DR Definition:

Adds behavior to an object in a flexible way without subclassing.

Slightly Longer Definition:

The decorator pattern can extend (decorate) an object's behavior by wrapping dynamically. A decorator "has-a" and "is-a" abstract class that is being extended. This allows us to "chain" behaviors that lead up to a concrete implementation of a method. The alternative is making many different subclasses for each unique case and creating a "class explosion" situation.

Hypothetical Use Case:

The decorator pattern could be used for point of sale system at a restaurant that calculates the total cost of an order. Suppose there is a burrito joint where customers can customize their burrito and decide their choice of meat, beans, if they want guac, etc. The base abstract class would be the burrito and the customer's options will be the decorators.

Pseudocode:

(fake C#/Java-ish code)

public abstract class Burrito
{
    string description = "Base Burrito";

    public string getDescription()
    {
        return description;
    }
    public abstract double cost();
}

public abstract class BurritoDecorator extends Burrito
{
    public abstract string getDescription();
}

public class BeefBurrito extends Burrito
{
    public Beef()
    {
        description = "Beef";
    }

    public double cost()
    {
        return 3.00;
    }
}

public class BeanBurrito extends Burrito
{
    public Bean()
    {
        description = "Bean";
    }

    public double cost()
    {
        return 2.00;
    }
}

public class Guac extends BurritoDecorator
{
    Burrito burrito;

    public Guac(Burrito burrito)
    {
        this.burrito = burrito;
    }

    public string getDescription()
    {
        return burrito.getDescription + ", Guac";
    }

    public double cost()
    {
        return .50 + burrito.cost();
    }
}

public class BurritoRestaurant
{
    public static void Main(string args[])
    {
        //customer wants a bean burrito with guac
        Burrito burrito = new BeanBurrito();
        burrito = new Guac(burrito);

        //your total is...
        Console.WriteLine(burrito.cost());
    }
}