Functional patterns in Java

Recently we started a journey through functional programming in Java with my articles “A new functional Java style” and “Mastering the new functional Java“. Now that we have a basic understanding about functional programming and what Java brings to us, I think it’s time to see how we can apply this to improve our existing code.

The introduction of functional programming in Java has brought new possibilities to the way we write code, having now much more flexibility.
We’ll be going through different common design patterns and show how functional programming helps improving them; making them less verbose, more readable and more maintainable.

Let’s start then!

Java design patterns

What is a design pattern?

A design pattern is a solution we normally apply to solve a common problem following some best practices guidelines.

Their main purpose is normally to improve the maintainability and readability of the code, guaranteeing that some known issues will be avoided if we follow a given pattern.

There are multiple design patterns and normally they’re divided into different groups:

  • Behavioural patterns

Are those that identify common communication patterns among objects. Some of the most popular behavioural patterns are: Strategy, Visitor, Chain of Responsibility, Template Method, Observer, Iterator, etc

  • Creational patterns

Are those that involve different mechanisms for objects creation. The most popular ones are: Factory, Builder, Prototype, Factory Method, etc

  • Structural patterns

Are those that identify ways of composing objects to make “enhanced” objects that serve a purpose. Some of them are: Adapter, Bridge, Proxy, Decorator, etc

We’re not going to go into details for all of them, because that would take a long time; instead we’re going to pick some of the most important patterns and see the way we used to implement them and how can we improve them now by making use of functional programming!

Factory method pattern

In the factory method pattern we provide an interface to the client to create an instance of the object, hiding the implementation details on how to create the objects.

Before Java introduced functional programming, this pattern could be implemented just by using if conditions, a switch case or even a Java Enum. (Please avoid switch statements by the way!)
My favourite implementation was the one that uses Java Enum, however, this is not always possible if we need to inject a dependency into the component we’re creating.

Let’s take a look at an implementation of this pattern in a non-functional way:

Java factory method pattern

As we can see, our Factory method accepts the type that we want to instantiate and also a “vehicle color”, which will be used to instantiate a vehicle of that color.
How would we use our implementation from a hypothetical client?

Vehicle redCar = VehicleFactory.instanceOfType(VehicleType.CAR, VehicleColor.RED);

It doesn’t look that bad but what are the issues with this implementation?

  • The use of if conditions to check type normally leads to code duplication
  • Adding a new type implies having to remember that we have to add a new if condition
  • We have to throw IllegalArgumentException, as it’s possible that we forgot to handle a new type
  • Harder to read than the functional approach, as we’ll see shortly
  • Slightly more verbose than the functional approach

So how can we implement this in a cleaner way taking advantage of Java functions? Let’s take a look at this:

Java functional programming

You will notice that we have reused the existing VehicleType enum and we have added a factory function to it; in our example we pass the method references for each of the constructors of our Vehicle implementations.
At first sight we can quickly notice that this class is cleaner and easier to read, reducing the clutter required just to create an instance of a given type.
Also, every element in the enum is forced to implement its factory method, so it’s impossible that we forget adding a factory for a recently added type! The Java compiler helps us here, guiding us to write the required changes when a new type is added; no additional mental effort has to be done from our side.

Let’s see now how can we use this implementation from a client:

Vehicle redCar = VehicleType.CAR.factory.apply(VehicleColor.RED);

Quite simple, right? As we have seen this implementation has a few advantages over the non-functional approach, I really hope you like it and start using it frequently.

Template method pattern

Template method is a pattern that allows us to define some common steps for an algorithm and then the subclasses override some of these steps with their specific behaviours for a particular step.

So how did we use to write this pattern in the “old way” in Java? Well, most of the times we had to use an abstract class and define abstract methods for each sub-step that could be overridden.
I have to admit that I used to do this in the past, probably because it was the only way, but now I see it as a very bad way of doing this.

Let’s see an example of how it used to be:

This is a very simple example, but basically each vehicle will print what initial check it’ll have to do before starting; in order to do that, each sub-class will have to override the preStartCheck abstract method.
For example if I modify Bus class to extend AbstractVehicle, it’ll force me to override the preStartCheck method.
For example, these steps for the bus could be:

@Override
void preStartCheck() {
        System.out.println("Check if every new passenger has paid for their tickets");
        System.out.println("Check if every passenger is seated");
}

This way is not ideal, as we have to create an abstract class and each of our subclasses has to extend this abstract class.
It’s messy, hard to follow and adds a considerable amount of clutter considering what it actually does.
As a rule of a thumb, I’d advice to avoid extending classes in Java, it’ll make your life easier in the long-term.

So what’s the alternative? Let’s move our start method to the Vehicle interface and we’ll make use of default modifier to provide a default implementation of our method in the interface.

As you can see, we now accept a Consumer to provide the preStartChecks for our class.
This is a very silly example, so some things will look a bit strange, like the use of a Consumer of Void. Don’t worry too much about it at the moment, this is just to exemplify how can we inject behaviour using Java functions.

So once we have that, how can we inject our pre-start checks logic? Let’s take a look:

And if we run our code it’ll print what we expect:

 Check if every new passenger has paid for their tickets
  Check if every passenger is seated
  Bus starting...

So that’s basically it, we have achieved exactly the same behaviour just by writing two lines in our interface; previously we needed an abstract class, an abstract method and each of our classes was being forced to implement the abstract methods.
This solution is much simpler, cleaner and readable, don’t you agree? I hope you do!

Builder pattern

The main purpose of the Builder pattern is to provide a way of constructing an object in steps, separating the construction logic from its representation.

The non-functional way of creating a Builder, although is very robust and very easy to use by a client, it has a problem; it’s very verbose.
So how can a functional approach help us in this case? Using a functional approach we’ll see how can we drastically reduce the amount of code needed to implement a Builder.

Let’s start first looking at how it used to look like before; you will probably like its expressiveness from a client’s perspective, but you won’t like its verbosity.
We’re going to recover the example shown in my article “Please stop the Java Optional mess!” and see how can we transform it to a functional style!

import java.util.Optional;
public class Customer {
private final String firstName;
private final String surname;
private final Integer age;
private final String address;
private final String phoneNumber;
private final Sex sex;
private Customer(Builder builder) {
this.firstName = builder.firstName;
this.surname = builder.surname;
this.age = builder.age;
this.address = builder.address;
this.phoneNumber = builder.phoneNumber;
this.sex = builder.sex;
}
public static Builder builderOf(String firstName, String surname) {
return new Builder(firstName, surname);
}
static class Builder {
private final String firstName;
private final String surname;
private Integer age;
private String address;
private String phoneNumber;
private Sex sex;
private Builder(String firstName, String surname) {
this.firstName = firstName;
this.surname = surname;
}
public Builder withAge(Integer age) {
this.age = age;
return this;
}
public Builder withAddress(String address) {
this.address = address;
return this;
}
public Builder withPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
return this;
}
public Builder withSex(Sex sex) {
this.sex = sex;
return this;
}
public Customer build() {
return new Customer(this);
}
}
public String getFirstName() {
return firstName;
}
public String getSurname() {
return surname;
}
public Optional<Integer> getAge() {
return Optional.ofNullable(age);
}
public Optional<String> getAddress() {
return Optional.ofNullable(address);
}
public Optional<String> getPhoneNumber() {
return Optional.ofNullable(phoneNumber);
}
public Optional<Sex> getSex() {
return Optional.ofNullable(sex);
}
static enum Sex {
FEMALE,
MALE
}
}
view raw Customer.java hosted with ❤ by GitHub

If you remember from that article, using that class from a client was quite easy; we could for example do something like this:

final Customer customer = Customer.builderOf("John", "Smith")
                .withAge(30)
                .build();

That’s quite nice, isn’t it? So our only problem in this case is the verbosity of the class, let’s see how functional Java can help.

First of all, the Builder embedded in our Customer class will be transformed to something like this:

Java functional Builder pattern

As you can see, now we accept a Consumer of Builder and we only provide one with method, instead of multiple withXXX methods! This is quite beneficial if our object has many fields.

Let’s take a look now at how could we use this implementation from a client’s perspective:

Java functional programming

That’s brilliant, right? We can specify all our fields in one single consumer instead, making our code more concise.

Let’s move on now to a different pattern, Strategy!

Strategy pattern

Strategy pattern is probably one of the most widely used design patterns; it’s normally used in every situation where we have to choose a different behaviour based on some property or input.

The only problem with the “old way” of writing a Strategy pattern is that in many cases we have to create a lot of classes and boilerplate code; this could make sense when these classes hold complex logic, but in many cases they’re even too simple to become a class!

It’ll be easier to see this with an example; in this example we’ll have to build a DeliveryPriceCalculator, which will depend on the plan that the customer has paid for.

First of all, these are the existing plans that we have:

Java Strategy pattern

Based on the existing plans, we’ll have to create an implementation for each plan; so we’ll need a DeliveryPriceCalculator interface and three implementations of this interface:

Java Strategy pattern
Java Strategy pattern
Java Strategy pattern
Java Strategy pattern

The implementations are quite simple, in some of them the customer will be charged a small percentage of the item price plus one dollar; for those customers paying for the business plan the delivery price will be just one dollar.

So what do we need in order to instantiate the class we need? We need a factory, which has been implemented in the same “old style” way that we showed earlier when we looked at Builder pattern; therefore we’ll omit its implementation. The code for this example can be found here in my github account in case you need it.
Let’s look at how the client will be using this then:

final PriceCalculatorFactory factory = new PriceCalculatorFactory();
final Item newItem = new Item(1L, new BigDecimal("12.99"));
final DeliveryPriceCalculator priceCalculator = factory.priceCalculatorFor(OldStylePlan.BASIC);
System.out.println("Delivery price is " + priceCalculator.priceFor(newItem));

So we can see again that the main problem with this pattern is its verbosity, the unnecessary clutter that we’re creating for something as simple as this. Do we really need all those classes? Can’t we make this simpler and more concise?
Let’s see how functional programming can come to the rescue here!

Instead of creating a new class for each implementation, we’re going to embed all this logic using Java functions.

Java functional programming

Please notice that we only need an enum to implement the whole strategy pattern in this case. Every plan is forced to implement its own delivery price calculator by providing a function!
That looks quite simple and concise to me, don’t you agree?

Also, the way the client uses this pattern has become simpler:

final Item item = new Item(1L, new BigDecimal("12.99"));
System.out.println("Delivery price is " + Plan.BASIC.deliveryPrice.apply(item));

Just one line and it’s really expressive now! I really hope you like this pattern, in my opinion it’s quite obvious that it helps reducing clutter and boilerplate code in our Java code.

Let’s take a look now at one last example, Chain of Responsibility pattern!

Chain of responsibility pattern

This pattern is very useful when we have to do different operations on an object in a given order, like a chain factory.

The non-functional way of implementing this pattern implied creating different classes, in a similar way to Strategy pattern. This used to be a bit verbose and it adds unnecessary complexity to our code.

How does it look like using non-functional programming?

I have to say beforehand that getting chain of responsibility pattern right is hard using a non-functional approach; our example is very very simple but still it’s very error-prone and difficult to get right. What do we need in order to implement this pattern?

We’re going to implement what I think is a good example for this pattern, a car wash machine. First of all we need an abstract class. Yeah, sorry…we need an abstract class and all the subclasses need to extend it. Remember to avoid this kind of situations in the future in Java, it doesn’t bring anything good!

Now, for the sake of brevity, I will include just one of the implementations to show how each of them would look like:

As you can see, in every step in our chain we’ll call applyTo if there’s a next step; when it reaches the end of the chain it will stop there.
How would we use this from our client?

final Car car = new Car();
final CarWashStep chain = new InitialWashStep();
chain.andThen(new SoapStep())
.andThen(new RinseStep())
.andThen(new PolishStep())
.andThen(new DryStep());
final Car finalCar = chain.applyTo(car);
System.out.println("Final car state is " + finalCar.washState());

If we execute this code we’ll see each of the steps being executed:

Car state transitioned to INITIAL
Car state transitioned to INITIAL_WASH
Car state transitioned to SOAP
Car state transitioned to RINSED
Car state transitioned to POLISHED
Car state transitioned to DRIED
Final car state is DRIED

So this implementation works, but it’s quite complex and verbose. Let’s see how functional programming can help here!

You’re going to be very impressed with how much code can we save with this approach!

That’s it! Impressive, right? In this example we can make use of the andThen method in Java Function and create a chain of functions using only Java built-in functions! No need for any custom classes actually, we have reduced our pattern to a few lines and now it’s also much more difficult to get it wrong.

One improvement that we should do is to extract those functions to a method, in that way you can express what that function is responsible for; for example we could have a soapStep method that creates that function.

So after applying that refactoring our chain of functions would look like this:

That’s much better, right? Now our chain of functions is easier to read, more meaningful and in those cases where our functions have complex logic, they could be easily unit tested!

So that’s it! I hope you’ve liked our examples and that you’ve enjoyed applying functional programming to achieve a more concise and readable code.

If you need to improve your understanding of Java Streams and functional programming in Java, I’d recommend that you read Functional Programming in Java: Harnessing the Power Of Java 8 Lambda Expressions; you can buy it on Amazon in the following link.

Also, please remember that you can find all these examples on Github here!

Conclusion

Functional programming is a big jump from an imperative approach, I’ve also been there before and I know it takes time to assimilate concepts and adapt our coding skills to this new approach; however, once you have a good command of it, you’ve learned all the benefits that it can bring to your code and how it can increase your productivity.

Many of the detractors of Java in the past few years commonly referred to the verbosity of the language and all the boilerplate code and clutter that it had to be generated; I actually think that they were right in many ways, but I also think that recent changes in Java are starting to close that gap, as we’ve seen in these examples.

Personally I see a bright future ahead for Java if they keep bringing this kind of changes to adapt our coding to these new times.

So this is all from me! I really hope you’ve enjoyed reading this article!
If you liked this article please follow me to get notified when a new article gets published! Also feel free to add any comments if you have any suggestions on what do you think it’d helpful to talk about on my next articles. I hope I see you again soon!

Thanks you very much for reading!

Up ↑

Take a look at our recommended books!

Ok!
X
%d bloggers like this: