The Corporate Code


Decorate your objects !
May 21, 2007, 14:14
Filed under: Decorator, Java, Tech, gof, patterns, programming

Today I will be discussing the decorator pattern. This pattern is used to add responsibilities to your objects at run-time rather then at compile time. You can find some examples of the decorator pattern by looking at the Java I/O API or the swing table API. Below is a small example of the decorator pattern in action :

LineNumberReader lrdr = new LineNumberReader(new FileReader(filename));

As you can see we wrap the FileReader into the LineNumberReader which adds certain functionalities to the FileReader.
As always, we start with the UML scheme for this pattern :

Decorator pattern UML

As you can see in the scheme above, The decorator will hold a reference to the decorated object and delegate it’s methods to the object. In this way we create a chain which will go all the way into the most inner class of the pattern. Below is a use case diagram which shows you how it works :

Decorator pattern Use Case
Because most of the methods in the decorator just pass the call to the reference object, we can create an abstract class of the decorator which has a default behavior which is to delegate the call to his reference object.
Let’s take a look at a code sample for this pattern. Imagine a Textview widget. We might want the textview to have some nice borders. By implementing this with the decorator pattern, the textview object doesn’t have to be modified in any way, in fact, it doesn’t even have to know anything about the borders to function correctly.

public abstract class AView {
public abstract void draw();
}

next up, we have an implementation of the Aview :


public class Textview extends AView {
public void draw();
// draw the textview
}

Now we create the decorator, which is an abstract class :

public abstract class BorderDecorator extends AView {
public abstract void draw();
}

And now for the actual Decorators :


public class 3Dborder extends BorderDecorator {
private AView component;
public 3Dborder(AView compo) {
This.component = compo;
}
public draw() {
component.draw();
// code to draw the 3D border
}
}
public class BevelBorder extends BorderDecorator {
private AView component;
public 3Dborder(AView compo) {
This.component = compo;
}
public draw() {
component.draw();
// code to draw the bevel border
}
}

And now for the usage :


AView tv = new TextView();
Tv = new 3Dborder(tv);
Aview tv2 = new BevelBorder(new TextView());


3 Comments so far
Leave a comment

What I like about the decorator pattern is that it’s a more flexible alternative to subclassing. Both “patterns” add functionalities to a class, but the decorator pattern doesn’t force you to define an hierarchy of functionalities like subclassing does (that is, you can combine whatever functionalities you want, in whatever order you want).
One of the (minor) problem with the decorator pattern for complex classes is that it involves a lot of “boilerplate” code like this:

public void doSomething(){
decorated.doSomething();
}

for every methods you don’t want to decorate. What I usually do in that case is to put all this boilerplate code in the abstract parent class Decorator (so that it becomes an abstract class without any abstract method).
I really wish I would use the decorator pattern more often but the problem is that I usually notice that I could use it after I’ve already implemented the “subclassing” version of the code.

PS: in the code, you forgot to make the BorderDecorator extends the AView class.

Comment by One of Eos' Erics

Oops, I forgot a “void” keyword in the code I posted.

Comment by One of Eos' Erics

Your exactly right, I’ve changed the example to correct the mistake :)

And I’ve changed your comment as well so that the void is in there :)

Comment by Tilleuil Doménique




Leave a comment
Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>