Design Patterns and You: The Decorator

So, I’ve been doing some work on my Framework for Package API-Based ADF BC (locking doesn’t work as-is, and it turns out the framework needs some pretty significant re-architecture to get it to), and between that and my regular work, I’ve been a little ADF’ed out. So for a couple of weeks or so, I’m going to do something I haven’t done a lot of in this blog, and post a bit about pure Java. This will, hopefully, contain techniques of interest to ADF developers, and I’m probably going to use some ADF-based examples, but I’m mostly going to be talking about “Java techniques that they don’t teach you in a 5-day Java class.”

While working on the new version of the Framework, I’ve run into some significant annoyances, by which I mean the sort of coding work that a monkey–or better yet, a tool–could do but is long and fiddly to do by hand. This isn’t something that will primarily bug your average ADF developer, but it’s a sufficiently common Java technique that it would be a useful add-on for any Java IDE, JDeveloper included. It’d be a neat project for my Copious Free Time, but for now I’m just going to throw it out there in case anyone’s interested: The automatic generation of a decorator. Even if you’re not interested in that, you might want to read this article, just to get a feel for an important design pattern.

What’s a decorator? I’m not talking about someone who comes over and rearranges your furniture, or even a weird crab. A “decorator” is a design pattern for object-oriented languages (such as Java), which allows you to incrementally add functionality to a wide range of objects. A decorator usually has the following features:

  • It implements (or extends) an interface or high-level abstract class
  • It has a constructor that accepts an instance of that same interface or abstract class, which we’ll call the decoratee.
  • It delegates most of its functionality to its decoratee, but might do a little pre- or post- processing for certain methods.

A Simple Decorator Example

In case that’s a bit abstract for you, here’s a simple example. Say you have an interface like the following:

public interface Animal {
   public void eat(Food food);
   public Object excrete();
   public void move(double x, double y, double z);
   public Animal reproduce();
}

You don’t know, or care, anything about the implementation of a particular Animal. But what you do wish is that, whenever an animal eats or moves, you got some kind of notification about what it ate or how far it moved, and suppose most implementations of Animal don’t tell you that. You can get this information by using a decorator.

public class CommunicativeAnimal implements Animal {
  private Animal _decoratee;
  public CommunicativeAnimal(Animal decoratee) {
    _decoratee = decoratee;
  }

  public void eat(Food food) {
    _decoratee.eat(food);
    System.out.println("Ate: " + food);
  }

  public Object excrete() {
    return _decoratee.excrete();
  }

  public void move(double x, double y, double z) {
    _decoratee.move(x, y, z);
    System.out.println("Moved: " + Math.sqrt(x*x + y*y + z*z));
  }

  public Animal reproduce() {
    return _decoratee.reproduce();
  }
}

Now, all you need to do is ensure that, whenever you’re given an animal, you wrap it in a CommunicativeAnimal, and you’ll always see this information printed to your console. So instead of calling:

talkTo(ZooKeeper.getInstance().findAnimal("lion"));

You’ll call:

talkTo(new CommunicativeAnimal(ZooKeeper.getInstance().findAnimal("lion")));

This way, if the lion eats or moves during the execution of talkTo(), you’ll get the information printed to your console. Note that you don’t have to know anything here about how lions are implemented; ZooKeeper could be a class from a library for which you don’t have source code, and for all you could care, a ZooKeeper’s findAnimal() method might return some bizarre anonymous inner class, so long as that class implements Animal. Your decorator will still work. You can also compose decorators: For example, if you have another Animal decorator that, say, prints out timing information about an Animal’s activities, you could do the following to get a timed, communicative version of that lion:

talkTo(new TimedAnimal(new CommunicativeAnimal(ZooKeeper.getInstance().findAnimal("lion"))));

As you might guess, this sort of thing might be very useful in a variety of contexts, which is why the Java libraries actually contain a number of these decorator classes, such as FilterInputStream and its myriad subclasses (which decorate InputStream), or the various (non-public) implementations returned by the Collections.synchronizedXXX(XXX) methods.

When It Gets Annoying

Now, lets suppose that, rather than needing to decorate the functionality of an Animal, you need to decorate the functionality of, say, an oracle.jdbc.OracleCallableStatement (ahem). OracleCallableStatement has, let’s see…about 450 methods, counting the ones it inherits from other interfaces. And for many of those methods, all you really want is something like the following (stmt is the decoratee here):

public InputStream getUnicodeStream(int parameterIndex) throws SQLException {
  return stmt.getUnicodeStream(parameterIndex);
}

public void registerOutParameter(int paramIndex, int sqlType, int scale, int maxLength) throws SQLException {
  stmt.registerOutParameter(paramIndex, sqlType, scale, maxLength);
}

That gets to be…a lot of typing. And notice that, while a good IDE (such as JDeveloper)’s “implement interface” functionality will generate all the method stubs for you, you still need to write every single method body. And most of them are trivial.

What the Extension Could Do

So here’s what I’d love to see an extension (especially a JDeveloper extension) do:

Generate an implementation of an interface, or a concrete subclass of an abstract class, with all of the following:

  • A private instance variable typed to the interface/abstract class (”decoratee”)
  • A constructor that takes an instance of the decoratee and assigns the instance variable to it
  • Implementations/overrides of all public methods to delegate to the decoratee, throwing any checked exceptions the decoratee method throws
  • For package interfaces (within the same package as the decorator), implementations of all package private methods to delegate to the decoratee, throwing any checked exceptions the decoratee method throws
  • For abstract classes, implementations/overrides of all accessible methods to delegate to the decoratee, throwing any checked exceptions the decoratee method throws

Of course, since you might want to decorate a class for which you don’t have the source code, this would have to be an option that allows you to specify anything on the classpath, rather than, say, a right-click menu on a Java source file in the Application Navigator.

Next week, I’m going to talk a bit about another design pattern I’ve found useful, and that I’d love a bit of tool help with implementing: The bridge, AKA the driver.