Wrapper (Decorator)

Wrapper (or Decorator) is one of the most important design patterns.

Wrappers are commonly used in:

The basic idea of a wrapper is to call-forward to an underlying object, while simultaneously allowing for new code to be executed just before and/or just after the call. Wrappers can be chained together, one after another. In this way, you can mix-and-match behaviors in various ways.

Note that this changes the behavior of an object, without needing to alter the implementation of a class, and also without needing to extend a class.

Here's an example implementation of a wrapper design pattern (other variations are also possible):


public interface TransformText {
  String render(String aInputText);
} 



/** Wrapper (Decorator) design pattern. */
public final class WrapperDemo {
  
  public static void main(String... aArgs){
    TransformText transformer = new BaseWrapper(new Echo());
    show(transformer.render("blah.")); // 'blah.'
    
    transformer = new Capitalize(new Echo());
    show(transformer.render("blah.")); // 'BLAH.'
    
    transformer = new RemovePeriods(new Capitalize(new Echo()));
    show(transformer.render("blah.")); // 'BLAH'
    
    transformer = new RemovePeriods(new Echo());
    show(transformer.render("blah.")); // 'blah'
  }
  
  private static void show(String aText){
    System.out.println(aText);
  }
  
  private static final class Echo implements TransformText{
    public String render(String aText) {
      return aText;
    }
  }
  
  /**
   This class both implements the interface AND is constructed 
   with an implementation of the same interface.
  */
  private static class BaseWrapper implements TransformText {
    BaseWrapper(TransformText aTransformText){
      fShowText = aTransformText;
    }
    /** Template method, calls 'before' and 'after' methods. */
    public final String render(String aText) {
      String text = before(aText);
      text = fShowText.render(text); //call-forward
      return after(text);
    }
    /** This default implementation does nothing.*/
    String before(String aText){
      return aText;
    }
    /** This default implementation does nothing.*/
    String after(String aText){
      return aText;
    }
    private TransformText fShowText;
  }
  
  private static final class Capitalize extends BaseWrapper {
    Capitalize(TransformText aTransformText){
      super(aTransformText);
    }
    @Override String before(String aText) {
      String result = aText;
       if (aText != null){
         result = result.toUpperCase();
       }
       return result;
    }
  }

  private static final class RemovePeriods extends BaseWrapper {
    RemovePeriods(TransformText aTransformText){
      super(aTransformText);
    }
    @Override String after(String aText) {
      String result = aText;
       if (aText != null){
         result = result.replace(".", "");
       }
       return result;
    }
  }
} 

The output of this class is:
blah.
BLAH.
BLAH
blah


See Also :
Template method
Would you use this technique?
Yes   No   Undecided   
© 2014 Hirondelle Systems | Source Code | Contact | License | RSS
Individual code snippets can be used under this BSD license - Last updated on September 21, 2013.
Over 2,000,000 unique IPs last year - Built with WEB4J.
- In Memoriam : Bill Dirani -