Fluent Interfaces in Java

Fluent interfaces in Java: images of a calm river

What is a fluent interface in Java? Why is it important, and how can it make your programming easier?

A fluent interface simplifies the way we use the interface of a class. It makes the class easier to use. It’s a way of designing an object’s API to allow us to chain multiple method calls together in a readable and intuitive manner. To implement it, we need to declare methods that return objects of the same type.

Fluent interfaces are all about readability. We use them to reduce syntactical “noise”, and to clearly express what the code does. We often code them as facade classes over existing code.

The fluent interface pattern is often used to build an internal Domain Specific Language (DSL). A domain-specific language is a computer language targeted at a specific type of problem, and is generally not usable to solve problems outside its particular domain.

POJO Example

As an example, here’s a standard POJO class without a fluent API. All setters return void as is usual:

public class Person {

    private String firstName;
    private String surname;
    // more data fields...

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    // more code...

} // end of class

Using it in code looks like this:

Person p = new Person();
p.setFirstName("Joe");
p.setSurname("Bloggs");

Now let’s change the setters to a fluent API. Instead of returning void, we specify Person as the return value, and return the current object itself, i.e. the this reference.

public class Person {

    private String firstName;
    private String surname;
    // more data fields...

    public Person setFirstName(String firstName) {
        this.firstName = firstName;
        return this;
    }

    public Person setSurname(String surname) {
        this.surname = surname;
        return this;
    }

    // more code...

} // end of class

Using it in code now looks like this:

// using method chaining
Person p = new Person().setFirstName("Joe").setSurname("Bloggs");

More intuitive, less coding and no repetition!

String and StringBuilder APIs

We all know the standard building block String class. It uses a fluent interface for most methods returning a String object, such as replace(), substring(), trim(), toLowerCase(), toUpperCase(), etc. They don’t return a reference to the same this object, but rather a brand-new String object. The methods can be chained together as follows:

String s = "Who is General Failure and why is he reading my hard disk?";
s = s.substring(0, 23).trim().toLowerCase();

Another example of a fluent interface is the overloaded append() methods of the StringBuilder and StringBuffer classes. These methods always return an instance of the same class.

Here is a simple example:

StringBuilder sb = new StringBuilder();
sb.append("My name is ")
  .append(name)
  .append(" ")
  .append(surname)
  .append(" and my age is ")
  .append(age);

The Streams API

An excellent example of fluent API design is the Java Streams API. We reduce verbose code by chaining stream-related method calls together, rather than using the traditional way of externally iterating over a collection. Manipulating streams of data using a fluent interface API allows us to express our intentions in a clear, declarative way.

Let’s look at a simple example using the standard fluent Stream map-reduce-filter paradigm. We first create a Stream object from a list of numbers with the static Stream.of() method. After that we can manipulate the resulting stream using its fluent API. After each method call, an object of the same Stream type is returned. We terminate the stream operation with a method that returns a different type, here a Collector that returns a String:

Stream<Integer> fibonacci = Stream.of(0,1,1,2,3,5,8,13,21,34,55,89,144);

String result = fibonacci.distinct()
                         .filter(n -> n % 2 != 0)    // odd numbers only
                         .limit(3)
                         .map(n -> "#" + n)
                         .peek(System.out::println)  // for debugging
                         .collect(Collectors.joining(", "));
System.out.println(result);

The Builder Design Pattern

The Builder design pattern is a creational design pattern that separates the construction of a complex object from its representation. The Builder class in the pattern usually implements a fluent interface that allows the step-by-step creation of objects. This interface makes it easy to use as the following code shows:

Person.Builder builder = Person.builder();

personBuilder = builder.firstName("Joe")
                       .surname("Bloggs")
                       .nickName("thebloggman")
                       .setAge(31)
                       .email("joe.bloggs@snailmail.com");

Person person = builder.build();

The Person.Builder class uses a fluent interface API. We first create a Person.Builder using the Person.builder() method. Then we chain multiple methods calls that set various attributes of a person. Each of these methods returns the same Person.Builder object. Finally, we call the build() method which returns a new Person object with the appropriate attributes set.

The Builder design pattern is a good example of the implementation of a fluent interface API.

The Interface Segregation Principle vs Fluent Interfaces

One of the downsides to fluent interfaces is that they are generally large interfaces. As such they have the potential to violate the Interface Segregation Principle (the I in the SOLID design principles).

As an example, the Stream interface has close to 40 methods in Java 8 and almost 50 in Java 21.

If we have created a facade class implementing a fluent interface on top of code that follows the SOLID design principles, we can limit the violations to that facade class.

Summary and Further Reading

To summarise:

  • APIs with fluent interfaces make code consuming them easier to write, read and understand.

  • Fluent APIs are harder to write, and can violate the Interface Segregation principle.

The term fluent interface was coined in 2005 by Eric Evans and Martin Fowler, even though that style of interface dates from the development of method cascading in the Smalltalk language in the 1970s. Martin Fowler’s original article is here.

There’s a nicely written technical article at Belief Driven Design on fluent builders.

As usual, Wikipedia has a very detailed page here.

The numbers used in the Stream example were from the Fibonacci sequence. It’s a very simple numerical sequence in which each number is the sum of the two preceding ones. For its simplicity, it has some fascinating properties and appears in many unexpected places, even in nature.

Was this interesting? Please share your comments, and as always, stay safe and keep learning!

Leave a Comment

Your email address will not be published. Required fields are marked *

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.