The Decorator Pattern

The idea is to augment an existing class with new functionalities without rewriting the existing code. There are two possibilities to do it:

Solution 1: Inherit if the class is not final.

Solution 2: Add a decorator class using composition.

Let’s say we want to program a draw shapes. We can create a Display interface that will be implemented by all of our classes.

public interface Display {

  public void draw();

}

Our basic class draws the shape

public class SimpleDisplay implements Display {

   public void draw() {
     // draw shape
   }

}

Now we want to fill the shape. We can extend what SimpleDisplay does with another class:

public class FillerDisplay {

   private Display display;

   public FillerDisplay(Display display) {
     this.display = display;
   }

   public void draw() {
     fill();
     display.draw();
   }

}

We can also add a zoom effect:

public class ZoomDisplay {

   private Display display;

   public ZoomDisplay(Display display) {
     this.display = display;
   }

   public void draw() {
      zoom();
      display.draw(); 
   }

}

So we can combine those decorators to obtain the result we want:

// a simple display
Display simple = new SimpleDisplay();

// a display filling the shape
Display fill = new FillerDisplay(new SimpleDisplay());

// a display that can zoom
Display zoom = new ZoomDisplay(new FillerDisplay(new SimpleDisplay()));

Notice we do not have to have a filler. A display can simply draw a shape and zoom. There are also ways to simplify the creation of the objects.

What can be trickier is accessing methods in one of the layers. For example, we can imagine that we want the FillerDisplay to use an image to fill the shape. In that case, we would add a method called setImageBackground() but it would be specific to FillerDisplay. To access that method, we would need to implement a getDisplay() in each layer, and we would have a code that looks like:

display.getDisplay().getDisplay()... getDisplay().setImageBackground(img)

which is not … very pretty … (Coding is art after all). What’s possible is to create a “shortcut” method in the client code if it is used frequently:

private Display getFillerDisplay() {
   return display.getDisplay().getDisplay()... getDisplay();
}

It can be lengthy code if each display is a generic:

LayerDisplay<ZoomDisplay<FillerDisplay<RandomDisplay<SimpleDisplay>>>>> display;

hmmm… so good. 🙂

Leave a comment

Design a site like this with WordPress.com
Get started