Some reader favorites:
EJB fundamentals and session beans
Create a scrollable virtual desktop in Swing
Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API
Software decorators, like cell phone faceplates, encapsulate some functionality that you can snap onto an existing object; for example, here's a code fragment that snaps sorting onto an existing Swing table model:
TableSortDecorator sortDecorator = new TableSortDecorator(table.getModel()); table.setModel(sortDecorator);
The preceding code swaps out a table's model for a decorator. After the swap, whenever the table accesses its model, it unknowingly accesses the sort decorator. The decorator adds sorting capabilities to the model it decorates, and delegates other functionality to the real model.
Like cell phones, software heavily reliant on inheritance includes a high percentage of statically defined objects. Just as a cell phone's antenna or speaker is statically defined at the factory, base classes and their extensions are statically defined at compile time. Because inheritance is static, it does not allow you to swap out an aspect of an object's behavior at runtime (such as the table model decorator in the code fragment above). Because you can use decorators much like Legos to snap together an object with desired behaviors at runtime, the Decorator design pattern proves far more flexible than inheritance.
In this article, I first introduce the Decorator pattern, starting with an example that shows how to use Java's I/O decorators. I then outline the Decorator pattern's statics and dynamics with UML class and sequence diagrams, respectively. I conclude with an example decorator that, as alluded to above, adds sorting to Swing tables.
Note: In the first installment of this column -- "Amaze Your Developer Friends with Design Patterns" -- I introduced Decorator, among other patterns. You may wish to read that introduction before proceeding with this more detailed look.
Decorator: Attaches responsibilities to objects at runtime. Decorators prove more flexible than inheritance, which attaches responsibilities to classes at compile time.
In "Amaze Your Developer Friends with Design Patterns," I described input streams and the Decorator pattern. Example 1 from that article demonstrates instantiating a line number reader:
Example 1. Instantiating I/O decorators
1. FileReader frdr = new FileReader(filename); 2. LineNumberReader lrdr = new LineNumberReader(frdr);
The preceding code creates a reader -- lrdr -- that reads from a file and tracks line numbers. Line 1 creates a file reader (frdr), and line 2 adds line-number tracking.
At runtime, decorators forward method calls to the objects they decorate. For example, in the code above, the line number
reader, lrdr, forwards method calls to the file reader, frdr. Decorators add functionality either before or after forwarding to the object they decorate; for example, our line number
reader tracks the current line number as it reads from an input stream.
Alternatively, of course, you could write Example 1 like this:
LineNumberReader lrdr = new LineNumberReader(new FileReader(filename));
Both methods outlined above adhere to the same construction idiom: wrapping objects recursively -- a hallmark of the Decorator design pattern.
The code in Example 2 below shows how to instantiate and use a line number reader. The example reads lines of text from a file and prints each line with its line number:
Example 2. Using I/O decorators
try {
LineNumberReader lrdr = new LineNumberReader(new FileReader(filename));
for(String line; (line = lrdr.readLine()) != null;)rticle.txt {
System.out.print(lrdr.getLineNumber() + ":\t" + line);
}
}
catch(java.io.FileNotFoundException fnfx) {
fnfx.printStackTrace();
}
catch(java.io.IOException iox) {
iox.printStackTrace();
}
Decorators represent a powerful alternative to inheritance. Whereas inheritance lets you add functionality to classes at compile time, decorators let you add functionality to objects at runtime.
Mechanical engineers study statics and dynamics. Statics analyze forces on objects that don't move very much -- bridges or buildings, for instance. Dynamics analyze forces on moving objects, typically in machines. The centrifugal forces on jet engine blades or clock pendulums are good examples.
Statics and dynamics have direct counterparts in the realm of software design patterns. Design pattern statics analyze class relationships specified at compile time, whereas design pattern dynamics analyze the runtime sequence of events in which objects participate. In this section, I show design pattern statics with UML class diagrams and design pattern dynamics with UML sequence diagrams.
Throughout the Java Design Pattern column, I will discuss the static and dynamic aspects of each design pattern we explore. Let's begin by examining the statics and dynamics of the pattern at hand -- Decorator.
Decorators decorate an object by enhancing (or in some cases restricting) its functionality. Those objects are referred to as decorated. Figure 1 shows the static relationship between decorators and the decorated.
Figure 1. Decorator class diagram. Click on thumbnail to view full-size image.
Decorators extend the decorated class (or implement the decorated interface), which lets decorators masquerade as the objects
they decorate. They also maintain a reference to a Decorated instance. That instance is the object that the decorator decorates. As an example of how the classes in the Decorator pattern
relate, Figure 2 depicts the static relationships among four decorators from the java.io package:
BufferedReaderLineNumberReaderFilterReaderPushbackReader
Figure 2. I/O decorators
BufferedReader and FilterReader are decorators just like the one shown in Figure 1. Both classes extend the abstract Reader class, and both forward method calls to an enclosed Reader. Because they extend BufferedReader and FilterReader, respectively, LineNumberReader and PushbackReader are also decorators.
Free Download - 5 Minute Product Review. When slow equals Off: Manage the complexity of Web applications - Symphoniq
![]()
Free Download - 5 Minute Product Review. Realize the benefits of real user monitoring in less than an hour. - Symphoniq