Decorator Design Pattern using lambdas

With the advent of lambdas in Java we now have a new tool to better design our code. Of course the first step is using streams, method references and other neat features introduced in Java 8.

Going forward I think the next step is to revisit the well established Design Patterns and see them through the functional programming lenses. For this purpose I’ll take the Decorator Pattern and implement it using lambdas.

We’ll take an easy and delicious example of the Decorator Pattern: adding toppings to pizza. Here is the standard implementation as suggested by GoF:

First we have the interface that defines our component:

public interface Pizza {
    String bakePizza();
}

We have a concrete component:

public class BasicPizza implements Pizza {
    @Override
    public String bakePizza() {
        return "Basic Pizza";
    }
}

We decide that we have to decorate our component in different ways. We go with Decorator Pattern. This is the abstract decorator:

public abstract class PizzaDecorator implements Pizza {
    private final Pizza pizza;
    
    protected PizzaDecorator(Pizza pizza) {
        this.pizza = pizza;
    }

    @Override
    public String bakePizza() {
        return pizza.bakePizza();
    }
}

we provide some concrete decorators for the component:

public class ChickenTikkaPizza extends PizzaDecorator {
    protected ChickenTikkaPizza(Pizza pizza) {
        super(pizza);
    }

    @Override
    public String bakePizza() {
        return super.bakePizza() + " with chicken topping";
    }
}

public class ProsciuttoPizza extends PizzaDecorator {

    protected ProsciuttoPizza(Pizza pizza) {
        super(pizza);
    }

    @Override
    public String bakePizza() {
        return super.bakePizza() + " with prosciutto";
    }
}

and this is the way to use the new structure:

Pizza pizza = new ChickenTikkaPizza(new BasicPizza());
String finishedPizza = pizza.bakePizza();   //Basic Pizza with chicken topping

pizza = new ChickenTikkaPizza(new ProsciuttoPizza(new BasicPizza()));
finishedPizza  = pizza.bakePizza();  //Basic Pizza with prosciutto with chicken topping

we can see that this can get very messy, and it did get very messy if we think about how we handle buffered readers in java:

new DataInputStream(new BufferedInputStream(new FileInputStream(new File("myfile.txt"))))

of course, you can split that in multiple lines, but that won’t solve the messiness, it will just spread it.
Now lets see how we can do the same thing using lambdas.
We start with the same basic component objects:

public interface Pizza {
    String bakePizza();
}

public class BasicPizza implements Pizza {
    @Override
    public String bakePizza() {
        return "Basic Pizza";
    }
}

But now instead of declaring an abstract class that will provide the template for decorations, we will create the decorator that asks the user for functions that will decorate the component.

public class PizzaDecorator {
    private final Function<Pizza, Pizza> toppings;

    private PizzaDecorator(Function<Pizza, Pizza>... desiredToppings) {
        this.toppings = Stream.of(desiredToppings)
                .reduce(Function.identity(), Function::andThen);

    }

    
    public static String bakePizza(Pizza pizza, Function<Pizza, Pizza>... desiredToppings) {
        return new PizzaDecorator(desiredToppings).bakePizza(pizza);
    }

private String bakePizza(Pizza pizza) {
    return this.toppings.apply(pizza).bakePizza();
}

}

There is this line that constructs the chain of decorations to be applied:

Stream.of(desiredToppings).reduce(identity(), Function::andThen);

This line of code will take your decorations (which are of Function type) and chain them using andThen. This is the same as

(currentToppings, nextTopping) -> currentToppings.andThen(nextTopping)

and it sure that the functions are called subsequently in the order you provided.
Also Function.identity() is translated to elem -> elem lambda expression.

Ok, now where we’ll we define our decorations? You can add them as static methods in PizzaDecorator or even in the interface:

public interface Pizza {
    String bakePizza();

    static Pizza withChickenTikka(Pizza pizza) {
        return new Pizza() {
            @Override
            public String bakePizza() {
                return pizza.bakePizza() + " with chicken";
            }
        };
    }

    static Pizza withProsciutto(Pizza pizza) {
        return new Pizza() {
            @Override
            public String bakePizza() {
                return pizza.bakePizza() + " with prosciutto";
            }
        };
    }
}

And now, this is how this pattern gets to be used:

String finishedPizza = PizzaDecorator.bakePizza(new BasicPizza(),Pizza::withChickenTikka, Pizza::withProsciutto);

//And if you static import PizzaDecorator.bakePizza:

String finishedPizza  = bakePizza(new BasicPizza(),Pizza::withChickenTikka, Pizza::withProsciutto);

As you can see, the code got more clear and more concise, and we didn’t use inheritance to build our decorators.

This is just one of the many design pattern that can be improved using lambdas. There are more features that can be used to improve the rest of them like using partial application (currying) to implement Adapter Pattern.

I hope I got you thinking about adopting a more functional programming approach to your development style.

UPDATE: Here you can find a video walkthrough of this article, created by my friends from Webucator:

If you want to see more of their tutorials you can visit Webucator site

Bibliography:

The decorator example was inspired by Gang of Four – Decorate with Decorator Design Pattern article

The refactoring method was inspired by the following Devoxx 2015 talks (which I recommend watching as they treat the subject at large):
Design Pattern Reloaded by Remi Forax
Design Patterns in the Light of Lambda Expressions by Venkat Subramaniam

 

Type-safing the Observer with mutually recursive bounds

The Observer is known as a behavioral pattern, as it’s used to form relationships between objects at run-time.  The definition provided in the original Gang of Four book on Design Patterns states:

   Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

The Java library implements a non-generic version of the Subject-Observer pattern in the package java.util with the class Observable and the interface Observer. The Observable class contains methods to register observers (addObserver), to indicate that the observable has changed (setChanged), and to notify all observers of any changes (notifyObservers), among others. The notifyObservers method may accept an arbitrary argument of type Object that is to be broadcast to all the observers. The Observer interface specifies the update method that is called by notifyObservers. This method takes two parameters: the first one, of type Observable, is the subject that has changed; the second, of type Object, is the broadcast argument.
We could, of course, create our own classes and not use those provided by the library, but isn’t it wonderful when someone else takes care of maintaining our code? So we’re going to use the provided library for this example.

Let’s see an example. Suppose we have a family with 4 members, mom, dad, a baby and a dog. When the little baby cries, mom changes his diaper, so we have the class Baby as an Observable and the class Mother as an Observer of the Baby:

public class Baby extends Observable {
   private String name;
   public Baby(String name) {
    this.name = name;
   }
   public void babyIsCrying() {
    setChanged();
    notifyObservers(name);
   }
}

public class Mother implements Observer {
   @Override
   public void update(Observable subject, Object param) {
    String babyName = (String) param;
    System.out.println(“Let’s change that diaper on “ + babyName + “!”);
  }
}


The father takes the dog for a walk when it barks, so the class Dog is another Observable and the class Father its Observer:
public class Dog extends Observable {
   private String name;
   public Dog(String name) {
    this.name = name;
   }
   public void barks() {
    setChanged();
    notifyObservers(name);
   }
}
public class Father implements Observer {
   @Override
   public void update(Observable o, Object arg) {
    String dogName = (String) arg;
    System.out.println(dogName + “, let’s go to a walk!”);
   }
}

At a first glance, everything seems to be working ok, but What if somebody understands wrongly the relationships and adds the Mother as an Observer of the Dog(the compiler wouldn’t complain about it and the runtime will sillently change the diaper on the dog and wouldn’t even notify us about the horrible mistake we did).
Let’s test it:
public class TestingLegacy {
   public static void main(String[] args) {
   Baby david = new Baby(“David”);
    Mother mom = new Mother();

    Dog rover = new Dog(“Rover”);
    Father john = new Father();

    // test mother-baby relationship
    david.addObserver(mom);
    david.babyIsCrying();
    // test father-dog relationship
    rover.addObserver(john);
    rover.barks();

    // delete observers to test wrong relatinships
    david.deleteObservers();
    rover.deleteObservers();

    System.out.println(“Add a wrong relationship and test.”);

    // add the father as the baby’s observer
    david.addObserver(john);
    // add the mother as the dog’s observer
    rover.addObserver(mom);

    david.babyIsCrying();
    rover.barks();
   }
}

The console outputs:
Let’s change that diaper on David!
Rover, let’s go to a walk!
Add a wrong relationship and test.
David, let’s go to a walk!
Let’s change that diaper on Rover!

To ensure that a Subject-Observer relationship is well established, we should use one of the nicest Java 5 feature: generics. They add stability to the code by making more of your bugs detectable at compile time. But there is a small problem, because Observable and Observer are part of the java docs, we can’t and shouldn’t change them. So to be able to add bounds, we will create stub classes with generic signatures but no bodies. We compile the generic client against the generic signatures, but run the code against the legacy class files. This technique is appropriate when the source is not released, or when others are responsible for maintaining the source.
So we can replace Observable and Observer with the type parameters S and O (for Subject and Observer). Then within the update method of the observer, you may call on any method supported by the subject S without first requiring a cast. Also, The appearance of Object in a method signature often indicates an opportunity to generify. So we should add a type parameter, A, corresponding to the argument type.
Here is our first version of stubs with two generic params:
public class Observable<O extends Observer<?, A>, A> {..}
public interface Observer<S extends Observable<?, A>, A> {…}

Now when creating a Mother-Baby relationship things work just fine. What about Mother-Dog? the compiler let’s us do the link, the runtime however throws a ClassCastExeption for this time.
class WrongBoundedBaby extends Observable<WrongBoundedMother, String>
class WrongBoundedMother implements Observer<Dog, String>

Exception in thread “main” java.lang.ClassCastException: bounds.WrongBoundedBaby cannot be cast to bounds.Dog
   at bounds.WrongBoundedMother.update(WrongBoundedMother.java:1)
   at java.util.Observable.notifyObservers(Observable.java:142)
   at bounds.WrongBoundedBaby.babyIsCrying(WrongBoundedBaby.java:28)
   at bounds.TestingLegacy.main(TestingLegacy.java:38)


So, not good enough, as the bug won’t be detected until run-time. We need S to be in scope in Observable so that it can be passed as a parameter to Observer, and we need O to be in scope in Observer so that it can be passed as a parameter to Observable.
class Observable<S extends Observable<S, O, A>, O extends Observer<S, O, A>, A>
interface Observer<S extends Observable<S, O, A>, O extends Observer<S, O, A>, A>

This is the last version of our classes:
class Baby extends Observable<Baby, Mother, String>
class Mother implements Observer<Baby, Mother, String>
class Dog extends Observable<Dog, Father, String>
class Father implements Observer<Dog, Father, String>

// COMPILE- error when adding the father as the baby’s observer
// david.addObserver(john);
// COMPILE- error when adding the mother as the dog’s observer
// rover.addObserver(mom);

The Java Generics and Collections book defines this type of bound as mutually recursive.

In conclusion, the Observer is a great design pattern with many implementations, but a junior dev can be easily tricked to use it wrongly. Adding the mutually recursive bounds helps us idetifying the problem at compile time and sleeping good at night when knowing that we did a great job.

For full source code, please see https://github.com/CrisIf/generics .


This post is part of the Java Advent Calendar and is licensed under the Creative Commons 3.0 Attribution license. If you like it, please spread the word by sharing, tweeting, FB, G+ and so on!