Decorator Pattern

CSC-430

Phillip Wright

The Decorator Pattern

Attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

AKA: Wrapper

OO Principle: Open/Closed

Classes should be open for extension, but closed for modification

The Decorator Pattern II

  • Allows for extension at runtime.
  • Allows you to modify the behavior of a class without actually changing it
    • …and without it even being aware of the decorators existence!

Example

public interface Duck{
  String fly();
}

Example II

public class BasicDuck implements Duck{
  private final FlyStrategy strategy;
  public BasicDuck(final FlyStrategy strategy){
    this.strategy = strategy;
  }

  // ...
}

Example III

public class StrongDuck implements Duck{
  private final Duck wrapped;
  public StrongDuck(final Duck d){
    this.wrapped = d;
  }

  public String fly(){
    return wrapped.fly() + wrapped.fly();
  }
}

The Decorator Pattern III

  • Avoids an explosion of subclasses
    • $ |base classes| \times |variations| $ (if we only use one variation)
    • $|base classes| \times 2^{|variations|}$ (any combination of variations)
    • $\infty$ (if we allow repeated variations)

The Decorator Pattern IV

  • Allows for added behavior before/after the components behavior
  • Allows for the complete replacement of a component’s behavior
  • Allows for enhancement of a given instance of a class.
  • Completely transparent to clients (unless they’ve done something ugly)

Transparency

  • A decorator and the object it decorates are unique
  • They, naturally, are not the same class
  • Accordingly, things like referential equality and casting may fail!

When To Use

  • Behavior needs to be added to an object instance dynamically and transparently
  • Behaviors may need to be removed from an instance
  • The number of variations make subclassing impractical (or impossible)
  • The class definition is not available for subclassing.

Strategy Vs. Decorator

We can think of a decorator as a skin over an object that changes its behavior. […] The strategy pattern is a good example of a pattern changing the guts.

Strategy Vs. Decorator

  • To use a strategy, the client must have knowledge of the strategy interface.
  • When using a decorator, the client can be completely ignorant of its existence.