Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Amaze your developer friends with design patterns

<strong>Java Design Patterns</strong> column kicks off with a look at three important design patterns

  • Print
  • Feedback

Page 5 of 6

Figure 3. Nest AWT containers

Because the AWT implements components and containers using the Composite pattern, Java applets and applications, like the one listed in Example 2, can easily nest components and containers in a tree structure. Additionally, components and containers can be treated uniformly.

The Decorator pattern

The java.io package provides, among other things, a set of classes for reading input streams. Known as readers, each of those classes has a name that follows the pattern: xxxReader.

Readers provide specialized functionality; for example, one reader reads from a file, another tracks line numbers, and yet another pushes characters back on the input stream. In all, eight different readers exist to read input streams.

It's often necessary to combine the capabilities offered by java.io readers; for example, you might want to read from a file, keep track of line numbers, and push certain characters back on the input stream, all at the same time. The java.io package's designers could have used inheritance to provide a wide array of such reader combinations; for example, a FileReader class could have a LineNumberFileReader subclass, which could in turn have a PushBackLineNumberFileReader subclass. But using inheritance to compose the most widely used combinations of reader functionality would result in a veritable explosion of classes. So how did the java.io package's designers create a design that allows you to combine reader functionality in any way you desire with only 10 reader classes? As you might guess, they used the Decorator pattern.

Instead of using inheritance to add functionality to classes at compile time, the Decorator pattern lets you add functionality to individual objects at runtime. That is accomplished by enclosing an object in another object. The enclosing object forwards method calls to the enclosed object and typically adds some functionality of its own before or after forwarding. The enclosing object -- known as a decorator -- conforms to the interface of the object it encloses, allowing the decorator to be used as though it were an instance of the object it encloses. That may sound complicated, but using decorators is actually quite simple. For example, the code listed in Example 3 uses a decorator to read and print the contents of a file. The code also prints line numbers and transforms "Tab" characters to three spaces.

Example 3. Use the Decorator pattern

import java.io.FileReader;
import java.io.LineNumberReader;
public class Test {
   public static void main(String args[]) {
      if(args.length < 1) {
         System.err.println("Usage: " + "java Test filename");
         System.exit(1);
      }
      new Test(args[0]);
   }
   public Test(String filename) {
      try {
         FileReader       frdr = new FileReader(filename);
         LineNumberReader lrdr = new LineNumberReader(frdr);
         for(String line; (line = lrdr.readLine()) != null;) {
            System.out.print(lrdr.getLineNumber() + ":\t");
            printLine(line);
         }
      }
      catch(java.io.FileNotFoundException fnfx) {
         fnfx.printStackTrace();
      }
      catch(java.io.IOException iox) {
         iox.printStackTrace();
      }
   }
   private void printLine(String s) {
      for(int c, i=0; i < s.length(); ++i) {
         c = s.charAt(i);
         if(c == '\t') System.out.print("   ");
         else          System.out.print((char)c);
      }
      System.out.println();
   }
}


If you use the code listed in Example 3 to read itself, you will get output that looks like Example 4.

  • Print
  • Feedback

Resources