The Decorator Pattern
An Introduction with Examples in Java |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
/** * 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 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); } }
/** * 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()); } }
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 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 Example