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

Decorate your Java code

A look at the Decorator design pattern

  • Print
  • Feedback

Page 4 of 4

  • You have many simple behaviors you would like to combine in numerous ways at runtime. Implementing the functionality with inheritance would result in a subclass explosion for every possible combination of behaviors.
  • You need to transparently add functionality to individual objects at runtime. Transparently means that existing classes need not have been modified to support the extra functionality; indeed, those classes are not aware that they are being decorated.
  • You want to restrict the use of an object's public methods. Instead of forwarding calls to a restricted method, a decorator can veto a method by throwing an exception from the wrapper method.


Homework

For this month's homework, implement a filter decorator -- extending the TableFilterDecorator class shown in Figure 8 -- that filters high-priced items in the table shown in Figure 6.

Homework from last column

If you look at the reader classes in java.io, you will find another decorator: BufferedReader. That class buffers reads, making it more efficient than an unbuffered reader. In light of this new discovery, you might decide to make Example 3 more efficient, like so:

FileReader       frdr = new FileReader(filename);
BufferedReader   brdr = new BufferedReader(frdr); // "mix in" a buffered reader
LineNumberReader lrdr = new LineNumberReader(brdr);


Here are the questions from last time, followed by their correct answers:

  1. Will the preceding code fragment compile?

    Yes (provided you import java.io.BufferedReader)

  2. How can you add two lines of code to the main method to see if the example runs faster?

    Add:

    long time = System.out.getCurrentMillis();
    ...
    System.out.println("Elapsed time: " + System.out.getCurrentMillis() - time);
    
  3. Will the modified example run more quickly? Why or why not?

    The application will run more slowly because LineNumberReader extends BufferedReader. Since line number readers are buffered to begin with, mixing in a buffered decorator will not improve performance; in fact, it will slow things down because the buffered decorator must forward calls, which slows things down.



Email

Thanks to everyone who sent me email after the first installment of this column. I received voluminous feedback with many interesting suggestions. As a notable example, Mark Riggle wrote:

I have an idea that you may already plan to incorporate. As you say in the article, object composition is preferable to inheritance. Many of the Gang of Four patterns reflect this concept by using delegation to pass a method to an object that will do the work. Strategy and Decorator are certainly two such patterns. The problem for languages like Java is the required dispatching methods. The decorator object must implement the methods of the object it is decorating, and most will likely just directly pass on to the decorated object. This is needed so that the client code is left unchanged. So whenever the decorated class changes its signature, the decorators must also be updated. This is a coupling problem solvable using some of the dynamic features added to Java. The most important one now is the dynamic proxy. Because many of the methods added to classes are merely forwarding calls to a delegated object, the dynamic proxy lets you do exactly that without actually adding the method definitions...

Thus, I think that the dynamic proxy and pattern use in Java go hand in hand, and a discussion on patterns needs to include a discussion on the dynamic proxy.



Mark is absolutely correct. Since JDK 1.3, Java directly supports the Proxy pattern. The Proxy pattern is closely related to the Decorator pattern, and is the topic for my next Java Design Patterns installment. In that article, I will show you how to use the built-in JDK support for the Proxy (and Decorator) patterns to implement the sort decorator example from this article.

About the author

David Geary is the author of Advanced JavaServer Pages (Prentice Hall, 2001; ISBN: 0130307041) and the Graphic Java series (Sun Microsystems Press). David has been developing object-oriented software in numerous object-oriented languages for 17 years. Since the GOF Design Patterns book was published in 1994, David has been an active proponent of design patterns, and has used and implemented design patterns in Smalltalk, C++, and Java. In 1997, David began working full-time as an author and occasional speaker and consultant. David is a member of the expert groups defining the JSP standard custom tag library and JavaServer Faces, and is a contributor to the Apache Struts JSP framework.
  • Print
  • Feedback

Resources