The Decorator Pattern With Java 8

In a recent post I described how the decorator pattern saved my day. I gave a small code snippet which contained the simplest way to create decorators but promised that there would be a nicer way with Java 8.

Here it is:

1

2

3

4

5

6

7

HyperlinkListener listener=this::changeHtmlViewBackgroundColor;

listener=DecoratingHyperlinkListener.from(listener)

.onHoverMakeVisible(urlLabel)

.onHoverSetUrlOn(urlLabel)

.logEvents()

.decorate(l->newOnActivateHighlightComponent(l,urlLabel))

.decorate(OnEnterLogUrl::new);

I’ll spend the rest of the post explaining how to get there.

I created a small sample project over at GitHub, which I will repeatedly reference from here. I can only recommend checking it out as it provides more details. It is public domain, so the code can be used without any limitation.

To continue on my last post it uses Swing’s
HyperlinkListener as a basis for decoration. This has the added advantage of keeping it simple as that interface is not generic and has only one method with only one argument (nice for lambda expressions!).

Overview

Like the other post, this one also doesn’t try to teach the pattern itself. (I found another nice explanation, though.) Instead, it recommends a way to implement it in Java 8 such that it becomes very convenient to use. As such, the post heavily relies on Java 8 features, especially default methods and lambda expressions.

The diagrams are just sketches and leave out a lot of details. More complete ones are easy to find.

Vanilla

In the usual realization of the pattern there is an interface (called
Component above), which will be implemented in the regular way by “normal” classes as well as all the decorators.

The Abstract Decorator Class

The decorators usually inherit from an intermediate abstract base class (
AbstractDecorator), which eases the implementation. It takes another component as a constructor argument and implements the interface itself by forwarding all calls to it. Thus, the behavior of the decorated component is unchanged.

It is now up to the subclasses to actually alter it. They do this by selectively overriding those methods, whose behavior they want to change. This often includes calls to the decorated component.

Creation Of Decorators

Usually, no special technique is used to create the decorators; just simple constructors. With complicated decorators you might even use a factory.

I’m a big fan of static constructor methods so I use them and make the constructors private. In order to keep callers of these methods in the dark about the details, I declare the return type of those methods as
Component as opposed to the more detailed type of the decorator. This can, for example, be seen in LogEventsToConsole.

My proposal changes the way decorators are created.

With Java 8

To use all the power of Java 8 I recommend to add a special interface for all decorators, the
DecoratingComponent. The abstract superclass for decorators implements that interface but, as before, only holds a reference to
Component.

It is important to notice that due to the definition of the new interface (see below) nothing changes for the concrete decorators. They are exactly identical in both realizations of the pattern. The abstract class also undergoes virtually no change (see further below) so switching to this solution has no noticeable costs.

The New Interface

The new interface
DecoratingComponent extends the basic component interface and provides factory methods for decorators. These are static or default/defender methods (so they are already implemented and would be final if they could be) and no abstract methods should be declared. This way, the new interface does not add an extra burden on the implementations further down the inheritance tree.

Regarding the following code samples: The generic ones were only created for this post. The ones which involve hyperlink listeners come from the demo application. Most notable is the
DecoratingHyperlinkListener (link to source file), which extends Swing’s HyperlinkListener.

Methods

The interface itself is actually quite simple and consists of three types of methods.

Adapter

To quickly move from a
Component to a
DecoratingComponent, the interface should have a static method which takes the first and returns the latter. Since
DecoratingComponent extends
Component and adds no abstract methods, this is trivial. Simply create an anonymous implementation and forward all calls to the adapted component.

The general approach would look like this:

1

2

3

4

5

6

7

8

9

10

11

staticDecoratingComponent from(Component component){

DecoratingComponent adapted=newDecoratingComponent(){

@Override

publicSomeReturn someMethod(SomeArgument argument){

returncomponent.someMethod(argument);

}

// ... more methods here ...

};

returnadapted;

}

In case of the
DecoratingHyperlinkListener it is much easier because it’s a functional interface so a lambda expression can be used:

1

2

3

staticDecoratingHyperlinkListener from(HyperlinkListener listener){

returnevent->listener.hyperlinkUpdate(event);

}

Generic Decoration

This is the essential method of the interface:

1

2

3

4

5

6

defaultDecoratingComponent decorate(

Function<?superDecoratingComponent,?extendsDecoratingComponent>

decorator){

returndecorator.apply(this);

}

It takes a function from one decorating component to another as an argument. It applies the function to itself to create a decorated instance, which is then returned.

This method can be used throughout the whole code to decorate any component in a simple and readable way:

1

2

3

4

5

6

7

8

9

10

11

12

13

Component some=...;

DecoratingComponent decorated=DecoratingComponent

// create an instance of 'DecoratingComponent' from the 'Component'

.from(some)

// now decorate it

.decorate(component->newMyCoolComponentDecorator(component,...));

// if you already have an instance of 'DecoratingComponent', it get's easier

But it is debatable whether these methods should really be added. While they are very convenient, a strong argument can be made against them as they create a circular dependency. Not only do the decorators know about the interface (which they implement indirectly via the abstract superclass), now the interface also knows its implementations. In general this is a pungent code smell.

The final call is not yet in on this but I recommend a pragmatic middle way. I let the interface know about the implementations which live in the same package. This will be the generic ones as they do not reference anything too concrete from the rest of my code. But I would not let it know about every crazy decorator I created deep in the bowels of the system. (And of course I would neither add all those decorators to the same package unless it’s already called the_kraken…)

Why an Extra Interface?

Yes, yes, all those Java 8 features are very nice but couldn’t you simply add these methods to
AbstractDecorator? Good question!

Of course, I could’ve just added them there. But I don’t like that solution for two reasons.

Single Responsibility Principle

First, that would blur the responsibilities of the classes. The new interface is responsible for decorating instances of
Component, the abstract superclass is responsible for enabling easy implementation of decorators.

These are not the same things and they do not change for the same reason. The new interface might change whenever a new decorator has to be included. The abstract class will change whenever
Component changes.

Type Hierarchy

If these methods were added to
AbstractDecorator, they could only be called on such instances. So all decorators would have to inherit from that class, which limits the range for future implementations. Who knows, maybe some really good reason comes up, why another class can not be an
AbstractDecorator.

Worse though, all decorators would have to expose the fact that they are an
AbstractDecorator. Suddenly there is an abstract class, which was only created to ease the implementation, creeping through the whole code base.

Other Differences

Besides introducing the new interface this variation of the pattern does not change much.

Changes To The Abstract Decorator Class

If you have access to the class, you should let it implement
DecoratingComponent instead of
Component. As no new abstract methods were introduced this entails no further changes. This is shown in the UML diagram above.

If you can not change the class, your decorators will only implement
Component. This will keep you from using their constructors to create a function which maps a component to a decorating component. As you need that function as an argument for the
decorate method, you have to change that method to look as follows:

1

2

3

4

5

6

7

8

9

// note the more general second type of the 'Function' interface

defaultDecoratingComponent decorate(

Function<?superDecoratingComponent,?extendsComponent>decorator){

// create the decorated instance as before

Component decorated=decorator.apply(this);

// since it is no 'DecoratingComponent' use 'from' to turn it into one

returnfrom(decorated);

}

Changes To The Decorators

No changes to those classes are necessary. Unless of course, you are one of those crazy people who use static factory methods. Than you would have to make sure that they declare their return type as
DecoratingComponent or you’re in the same situation as when the abstract superclass can not implement the new interface. If you can not change the decorator classes, the same solution works here.

Example

So let’s look at the snippet from above again:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// create a 'HyperlinkListener' with a method reference

HyperlinkListener listener=this::changeHtmlViewBackgroundColor;

// decorate that instance with different behaviors

// (note that each call actually returns a new instance

// so the result has to be assigned to a variable)

listener=DecoratingHyperlinkListener

// adapt the 'HyperlinkListener' to be a 'DecoratingHyperlinkListener'

// (looks better if it is not on its own line)

.from(listener)

// call some concrete decorator functions

.onHoverMakeVisible(urlLabel)

.onHoverSetUrlOn(urlLabel)

.logEvents()

// call the generic decorator function with a lambda expression

.decorate(l->newOnActivateHighlightComponent(l,urlLabel))

// call the generic decorator function with a constructor reference

.decorate(OnEnterLogUrl::new);

Reflection

We saw how Java 8’s static and default interface methods can be used to create a fluent API for the decorator pattern. It makes the code more concise and more readable at the same time while not interfering with the pattern’s mechanism.