Further Deprecating the Decorator Pattern

Design Patterns Book
It's only fair to share...Share on Google+0Share on Facebook0Tweet about this on TwitterShare on LinkedIn0Email this to someone

In the last post, we saw ways to replace the decorator pattern for static use cases. If you want to decorate functional interfaces though, there is another whole class of use cases, in which the decorator pattern may not be the most suitable solution.

Scenarios

Let us consider a few typical scenarios, where dynamic decorations could be applied:

  • Input modification: For example, a method that computes the distance  between two points, where you want to dynamically translate one of the points.
  • Output modification: For example, limiting the possible return value range.
  • Side-effects: Logging, authentication, etc.

While the decorator pattern is a viable approach to tackle all of these problems in general, there are special cases, in which it might just be overkill. The pattern is based on an interface, and the cases I am talking about, are those in which this interface is a simple one consisting of just one method (@FunctionalInterfaces in Java).

The side effecting scenarios are typically not dynamic decorations – usually you know at compile-time, what you want to log or authenticate. So for this post, let’s consider an input modification scenario:

Imagine a simple sensor-actuator system. We process some sensor values with nifty business logic and the output is sent to an actuator in order to do something. The actuator could do anything from vibrating your phone to accelerating your car. The details don’t matter here. What matters though, is that we want to be able to support different manufacturers for these actuators. Let’s make a few more assumptions for the sake of this discussion:

  • Each actuator is directed by sending it a given power level.
  • Each manufacturer’s actuator differs in the minimum and maximum supported power levels.
  • We have some way to read these limits from a file/database/etc.
  • We have the (obvious by now) requirement that we must not send an actuator an invalid power level.

Granted, this may be solved with a static decorator usage by decorating the accessor interface with a concrete decorator, which does two things: 1. it reads the limits and 2. it enforces them. True to the single responsibility principle, we’d like to find a cleaner way and would leave the limit reading to a separate class to have a side-effect free decorator.

For the remainder of this post, image this simplistic interface for the actuators:

public interface Actuator {
    void act(int power);
}

Traditional solution

Let’s solve this problem with a standard decorator-based implementation. First, we assume we have a class already, which reads the limit values. Next, in order to correctly implement the decorator pattern, we need a decorator class for actuators:

public class ActuatorDecorator implements Actuator {
    
    private final Actuator decoratee;
    
    public ActuatorDecorator(Actuator decoratee) {
        this.decoratee = decoratee;
    }

    @Override
    public void act(int power) {
        decoratee.act(power);
    }
}

Our limit enforcer is the a concrete decorator derived from it:

public class ActuatorLimitDecorator extends ActuatorDecorator {

    private final int lowerLimit, upperLimit;

    public ActuatorLimitDecorator(Actuator decoratee, int lowerLimit, int upperLimit) {
        super(decoratee);
        this.lowerLimit = lowerLimit;
        this.upperLimit = upperLimit;
    }

    @Override
    public void act(int power) {
        int limited = Math.max(lowerLimit, Math.min(upperLimit, power));
        super.act(limited);
    }
}

Finally, we bring it all together to decorate a concrete implementation, which will look something like this. Just imagine that the lower and upper limit have been retrieved via some reader.

Actuator concreteImplementation = System.out::println;
Actuator result = new ActuatorLimitDecorator(concreteImplementation, 10, 30);
IntStream.of(5, 8, 13, 21, 34).forEach(result::act);
// prints: 10, 10, 13, 21, 30

First of all, why do I consider this a dynamic decoration instead of a static one? It’s not really, at least not in the way it’s shown here. But imagine that the power values we calculate satisfy certain lower and upper limits already. If a manufacturer’s actuator supports the whole range of levels we could possibly be throwing at it, then we would not need the decorator at all. Such a dynamic decoration could easily be imagined above, where result would be assigned the concrete implementation instead, if the limits are sufficiently large. Hence, we could choose at runtime, depending on the concrete actuator, whether to decorate the implementation or not.

Functional decoration

Now all of this was just the standard decorator pattern. It’s been around for over 20 years, and we know by now it isn’t the worst idea to realize things like this. But it’s 2015, and even Java now supports lambda expressions and higher-order functions, so we may ask ourselves: do these new (for Java at least) language features somehow affect what we can do in such a case? And indeed, since the decorated interface is a functional interface, we have another option available now.

IntUnaryOperator lowerLimiter = i -> Math.max(10, i);
IntUnaryOperator upperLimiter = i -> Math.min(30, i);
IntUnaryOperator limiter = lowerLimiter.andThen(upperLimiter);
Actuator decorated = power -> concreteImplementation.act(limiter.applyAsInt(power));
IntStream.of(5, 8, 13, 21, 34).forEach(decorated::act);
// also prints: 10, 10, 13, 21, 30

Again, we assume that the lower and upper limits have been properly retrieved from somewhere. Since this is Java, function composition is barely supported, hence, the explicit lambda expression for the decorated actuator. Functionally, this has the same effect as the standard approach above, but it has its own pros and cons, which may make it the preferrable approach in some cases.

Disadvantages

Let’s first start discussing the arguments against this way of decorating:

  • No explicit “decorator”/”decoration”. Design patterns are an implementation solution as much as a language we use to talk to each other. If you tell a fellow software developer that you have “decorated” something, or that you have written a “decorator” for X, then we all know what you’re talking about. Functional composition is well-known too of course, but it’s usage for decorating behavior is something not everyone will immediately grasp.
  • No support for finding the decorator again for re-use. When you have a concrete decorator class, you can find it in simple ways – auto completion or type hierarchy will show you that such a decorator exists and you may be able to reuse it the next time. Functions (at least in Java) are not as easily findable.
  • The approach is only viable for decorating when the interface has a single method (or more precisely, we are decorating methods rather).

Advantages

Let’s take a look at the shiny side of the coin now:

  • Size: No need to define a decorator and concrete decorator class. Take a look at the traditional approach above and how much code was needed for the same functional limit-decorating behavior. That’s about 30 lines of code saved already.
  • Compositionality. A typical advantage of functional approaches: since the decoration is itself just another function, it is easily composable. I explictly split up the lower and upper limit in the above example to show how easy it would be to compose these two decorations.
  • Free of original interface: when you take a closer look, you’ll notice that we have an IntUnaryOperator as “concrete decorator”, which doesn’t have anything to do with the Actuator interface. This makes reuse of such functions much simpler, then binding them to an interface.
  • Partial decoration: since decoration is performed via a lambda expression, we are free to apply decorations to any argument. If our example’s interface method contained a second argument, like a time for how long the given power level should be applied, then we might just want to decorate the power argument on its own.

Summary

We have seen in the previous post how a language feature like traits can have significant advantages over the traditional decorator pattern. In this post, we have seen a similar case, where the language feature of higher-order functions/lambda expressions offers a different option. Which one should you choose though? If you’re working in Scala, then traits are clearly better than a decorator (since the interface and the base decorator class basically are the same trait already) for static use cases. In Java, both for static and dynamic use cases, it typically depends on the interface. For functional interfaces with just one method, their (maybe implicit) intention is already to be used via lambda expressions. Hence, these interfaces not only lend themselves to a decoration as described in this post, but I’d argue that would also be the preferred way, since the usage of the decorator pattern via separate decorator classes conceptually clashes with the idea of lambda-fied instances. For more complex interfaces (complex as in having more than one method) in a dynamic setting though the traditional decorator pattern still remains a viable alternative.

On a side-note, higher-order functions have been used for this purpose in functional programming (FP) languages for decades. Since composition of functions is so elementary in FP, there doesn’t even seem to be a name for this technique (at least I’m not aware of one, nor would it need one in FP).

It's only fair to share...Share on Google+0Share on Facebook0Tweet about this on TwitterShare on LinkedIn0Email this to someone