JMU
The Decorator Pattern
An Introduction with Examples in Java


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu


Motivation
Examples of Use
A Model of the Decorator Pattern
images/decorator_pattern.gif
An Example
images/decorator_pattern_printer-example.gif
An Example (cont.)
javaexamples/decorator/Printer.java
        /**
 * The requirements of a Printer
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public interface Printer
{
    /**
     * Print the given String
     *
     * @param text   The String to print
     */
    public abstract void print(String text);    
}

        
An Example (cont.)
javaexamples/decorator/ConsolePrinter.java
        /**
 * Prints text to the console
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class ConsolePrinter implements Printer
{
    /**
     * Print the given String
     *
     * @param text   The String to print
     */
    public void print(String text)
    {
       System.out.print(text);       
    }
    

}
        
An Example (cont.)
javaexamples/decorator/PrinterDecorator.java
        /**
 * An abstract decorator of Printer
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public abstract class PrinterDecorator implements Printer
{
    protected Printer     decorated;
    
    /**
     * Explicit Value Constructor
     *
     * @param decorated    The Printer to decorate
     */
    public PrinterDecorator(Printer decorated)
    {
       this.decorated = decorated;       
    }
    

    /**
     * Print the given String
     * (required by Printer)
     *
     * @param text   The String to print
     */
    public void print(String text)
    {
        decorated.print(text);
    }
}
        
An Example (cont.)
javaexamples/decorator/UppercasePrinter.java
        /**
 * A Printer that always prints in uppercase
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class UppercasePrinter extends PrinterDecorator
{
    /**
     * Explicit Value Constructor
     *
     * @param decorated    The Printer to decorate
     */
    public UppercasePrinter(Printer decorated)
    {
       super(decorated);       
    }
    

    /**
     * Print the given String
     * (required by Printer)
     *
     * @param text   The String to print
     */
    public void print(String text)
    {
       decorated.print(text.toUpperCase());       
    }
}

        
An Example (cont.)
javaexamples/decorator/WrappingPrinter.java
        import java.util.*;

/**
 * A Printer that wraps at word boundaries
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class WrappingPrinter extends PrinterDecorator
{
    protected int         width;
    

    /**
     * Explicit Value Constructor
     *
     * @param decorated    The Printer to decorate
     * @param width        The maximum width
     */
    public WrappingPrinter(Printer decorated, int width)
    {
       super(decorated);       
       this.width = width;       
    }
    

    /**
     * Print the given String
     * (required by Printer)
     *
     * @param text   The String to print
     */
    public void print(String text)
    {
       int                    required, used;       
       String                 token;       
       StringTokenizer        st;
       
       st   = new StringTokenizer(text);
       used = 0;       

       while (st.hasMoreTokens())
       {
          token    = st.nextToken();
          required = token.length();
          
          if ((required + used + 1) > width)
          {
             decorated.print("\n");
             decorated.print(token);             
             used = required + 1;
          }
          else
          {
             if (used != 0) 
             {
                decorated.print(" ");
                ++used;
             }
             
             decorated.print(token);
             used += required;             
          }
       }
    }
}

        
An Example (cont.)
javaexamples/decorator/Driver.java
        /**
 * An application that demonstrates the use of the
 * Decorator Pattern
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class Driver
{
    /**
     * The entry point
     *
     * @param args   The command line arguments
     */
    public static void main(String[] args)
    {
       Printer           printer;       
       String            text;
       

       text = "This is the text that we will use " +
              "to demonstrate the capabilities "   +
              "of different Printer objects.";
       

       printer = new ConsolePrinter();
       printer.print(text);       

       System.out.print("\n\n");       

       printer = new UppercasePrinter(new ConsolePrinter());
       printer.print(text);       

       System.out.print("\n\n");       

       printer = new WrappingPrinter(new ConsolePrinter(), 20);
       printer.print(text);       

       System.out.print("\n\n");       

       printer = new WrappingPrinter(
                     new UppercasePrinter(
                         new ConsolePrinter()), 20);
       printer.print(text);       
    }
    
}

        
An Alternative Implementation
An Alternative Implementation (cont.)

An Example

images/decorator_pattern_graphics-example.gif