When designing a system that has many combinations of similar items with different behaviors, it can be tempting to create subclasses from a parent class. In small cases, this works well. However, when there's possibly hundreds or thousands of possible combinations, the reasoning behind the saying "prefer composition over inheritance" becomes clear. One way to utilize composition when creating similar groups of items is to adopt a Decorator Pattern**.

Assumptions

What is the Decorator Pattern?

A decorator is a structural design pattern that allows new behavior to be dynamically given to an object without affecting other classes.

<div style="width:100%; margin:auto;text-align:center;"><img src="https://www.devmaking.com/img/topics/designpatterns/DecoratorPattern_01.png" alt="Decorator pattern UML diagram." style="max-width:95%;"> </div>

> The decorator pattern is sometimes referred to as a wrapper class!

Decorators are useful when you want to add behavior at runtime instead of using subclasses to define individual cases. In addition to this, it doesn't require opening up old classes to extend, adhering to the Open Closed principle.

Conceptualization

To show the decorator pattern in use, we will be designing a fantasy loot system where our equipment can have "elemental effects" such as flames, ice, and dark, among others. We want to create a design where equipment can have multiple elemental effects stacked on them, such as a staff with a flame and ice elemental effect:

<div style="width:100%; margin:auto;text-align:center;"><img src="https://www.devmaking.com/img/topics/designpatterns/DecoratorPattern_02.png" alt="fantasy sword decorator UML diagram" style="max-width:95%;"> </div>

Why not sub-classing?

Creating subclasses to exhaustively account for each type of item would quickly get out of hand; the total number of sub classes would be the product of all the item variations and all combinations of elemental effects!

If we have 3 elemental effects, we can create 6 unique combinations with them (using at least 1 effect, that is). If there are 10 types of equipment items in the game, that's still 60 subclasses to create! For this reason, a decorator pattern will help us manage the headache.

Using a Decorator

<div style="width:100%; margin:auto;text-align:center;"><img src="https://www.devmaking.com/img/topics/designpatterns/DecoratorPattern_03.png" alt="sword and elemental effects" style="max-width:95%;"> </div>

To implement our loot system, we want our concrete items and abstract decorator class to implement the same interface. The abstract decorator class will manage a reference to an object that is of type EquipmentItem to allow for recursive calling of the readStats() method.

As an example of a concrete item, we'll be creating a SimpleSword concrete class, in addition to three elemental effects: FireEffect, IceEffect, and DarkEffect.

Before we get too far ahead of ourselves, let's implement the EquipmentItem interface in addition to our two inheriting classes, SimpleSword, and ElementalEffect:

/* pseudo-code */
interface EquipmentItem {
   String readStats();
 }

// Concrete item example class:
class SimpleSword implements EquipmentItem {
   String readStats() {
     return "A mighty sword!\n";
   }
 }

// Our decorator class:
abstract class ElementalEffect implements EquipmentItem {
   // Reference to an equipment item:
   protected EquipmentItem equipment;
   // Constructor:
   ElementalEffect(EquipmentItem item) {
     item = equipment
   }
   // Implementing base functionality for our elemental effect.
   String readStats() {
     return equipment.readStats();
   }
 }

With the core classes implemented, let's create the effects:

class FireEffect extends ElementalEffect {
   FireEffect(EquipmentItem item) {
     super(item);
   }
   
   // Override implementation of readStats():
   String readStats() {
     // We're adding a tab (\t) and a newline with each stat.
     return equipment.readStats() + "\t" + "Has a fire effect.\n";
   }
 }

class IceEffect extends ElementalEffect {
   IceEffect(EquipmentItem item) {
     super(item);
   }
   
   String readStats() {
     return equipment.readStats() + "\t" + "Has an ice effect.\n";
   }
 }

class DarkEffect extends ElementalEffect {
   DarkEffect(EquipmentItem item) {
     super(item);
   }
   
   String readStats() {
     return equipment.readStats() + "\t" + "Has a dark effect.\n";
   }
 }

> When reading out the stats, we want to recursively read the prior added stats, then insert our stat at the end.

With all the classes implemented, we can see what it looks like in a client setting:

static void main(String[] args) {
   
   EquipmentItem sword = new SimpleSword();
   // prints "A mighty sword!"
   print(sword.readStats());
   
   EquipmentItem flameSword = new FireEffect(sword);
   EquipmentItem iceFlameSword = new IceEffect(flameSword);
   EquipmentItem darkIceFlameSword = new DarkEffect(iceFlameSword);
   
   print(darkIceFlameSword.readStats());
   /*
   Output:
          A mighty sword!
           Has a fire effect.
           Has an ice effect.
           Has a dark effect.
   */
   
   
   // Alternatively, could construct the sword like this:
   EquipmentItem superSword = new DarkEffect(
         new IceEffect(
         new FireEffect(
           new SimpleSword()
   )));
   
 }

> Further practice: implement this in your favorite language with SimpleStaff, SimpleHelmet, and SimpleShield item classes!

Using The Decorator Pattern in Real Life

> This article was originally written a year prior to this new section, which I am writing today on September 5, 2020.

When I set out to write the Design Patterns articles, I wanted to make sure that I was creating examples that would stick and were comprehensible to the reader. Being that you're reading this, it's very likely you've already seen the pizza topping example, or even the UI Window example in your research. From an educational standpoint, these examples do a good job of displaying the intent of the Decorator Pattern, but fail at being proper use-cases. The loot system example above is another example of this issue: successfully showcasing the mechanics of the Decorator Pattern, but failing at the most important task of being a better solution to a problem.

In a real-life example of creating the loot system, you'd probably want something closer to this:

/*pseudo-code*/
public abstract class EquipmentItem {
   List&lt;ElementalEffect&gt; effects;

   public void addEffect(ElementalEffect effect) {
       this.effects.add(effect);
   }

   public abstract void getItemName();

   public String readStats() {
       String result = this.getItemName();
       for(effect : this.effects)  {
           result += effect.readStats();
       }

       return result;
   }
}

public class Sword extends EquipmentItem {
   public void getItemName() {
       return "A mighty sword!";
   }
}

> You could do almost the exact same thing for the famous pizza topping example as well; the number one thing that those examples don't address is how to remove a topping the customer doesn't want.

The main difference is that the above implementation allows for elemental effects to still be dynamically added, even dynamically removed, and the logical hierarchy remains in-tact. What I mean by logical hierarchy is this: in the original example, you "wrap" the previous item inside a new effect, meaning you would be working with an effect object that has equipment instead of an equipment object that has effects. This issue of logical hierarchy isn't the fault of the Decorator Pattern; it's the fault of the example -and the many like it- being a poor real-world use of the Decorator Pattern.

This has probably left you wondering the same thing as me: "What's a good use of the Decorator Pattern, then?"

IO Streams

The best use-case of the Decorator Pattern I was able to find in a real-world scenario was in the InputStream library within Java; classes implementing the InputStream base class make use of the Decorator pattern to delegate resoponsibilities when it comes to reading and writing data.

> .NET contains a similar library for the same purposes.

Consider for a moment that we have a file with data about our sword object in it. We also chose to gzip the file. If we want to acquire the data, we use the Decorator Pattern to work our way up through composition. The following example was inspired by StackOverflow user BalusC in <a href="https://stackoverflow.com/a/6366543" target="_blank" style="color:inherit">this article</a>:

   // Create a file input stream:
   FileInputStream fInputStream = new FileInputStream("swordData.gz");
   // Unzip the data
   GzipInputStream gInputStream = new GzipInputStream(fInputStream);
   // Deserialize the data:
   ObjectInputStream oInputStream = new ObjectInputStream(gInputStream);

   // Deserealize the sword into an object:
   Sword mySword = (Sword)oInputStream.readObject();

   // ...
   oInputStram.close();

The Decorator Pattern is used here to avoid needing to subclass every possible combination of file readers, so the user can mix-and-match for their specific use-case! If you wanted to buffer the input, you could do so easily.