Another builder pattern for Java

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

Whenever you have a domain object, data transfer object, parameter object or any other object that can’t be instantiated with constructor parameters only, you need to create a builder for its class.

The great thing about Java is that it is statically typed so a builder can give you compiler errors if you forget to set the compulsory parameters. If you use the builder in this pattern, you also get a very fluent interface that imposes order on the parameters. When using the builder, your IDE will suggest the next parameter to set.

Problem

An object is to be initialized and it takes a number of attributes to do that. Some of the attributes are compulsory while others are optional. You wish not set up a long parameter list as your clients may make mistakes by placing the arguments incorrectly.

Consider a class representing email message objects:

public class EmailMessage {

    private String from;
    private String to;
    private String subject;
    private String content;
    private String mimeType;  // optional

    public EmailMessage(String from, String to, String subject, String content) {
        this(from, to, subject, content, null);
    }

    public EmailMessage(String from, String to, String subject, String content, String mimeType) {
        this.from = from;
        this.to = to;
        this.subject = subject;
        this.content = content;
        this.mimeType = mimeType;
    }

Now that will make it possible to make a mistake, although there is a natural order to the arguments.

new EmailMessage("gojko@example.com", "me@crisp.se", "hello comrade", "some content");

Solution

To make it more readable, we could use a builder:

         EmailMessage.builder()
                 .from("gojko@example.com")
                 .to("me@crisp.se")
                 .subject("hello comrade")
                 .content("Some content")
                 .build();

This makes it more obvious to anyone reading the client code about what is going on.

The implementation of the builder is an inner class.

    private EmailMessage() {}

    public static Builder builder() {
        return new EmailMessage.Builder();
    }

    public static class Builder {
        private EmailMessage instance = new EmailMessage();

        public Builder() {
        }

        public Builder from(String from) {
            instance.from = from;
            return this;
        }

        public Builder to(String to) {
            instance.to = to;
            return this;
        }

        public Builder subject(String subject) {
            instance.subject = subject;
            return this;
        }

        public Builder content(String content) {
            instance.content = content;
            return this;
        }

        public Builder mimeType(String mimeTypeName) {
            instance.mimeType = mimeTypeName;
            return this;
        }

        public EmailMessage build() {
            return instance;
        }
    }

However, this is version 1 and so looked my builders for long, what can be better?

Firstly is the compulsory and optional parameters, we must check that the compulsory is all there. We could use exceptions for that. A revised “Builder.build”:

        public EmailMessage build() {
            assert instance.from != null;
            assert instance.to != null;
            assert instance.subject != null;
            assert instance.content != null;
            return instance;
        }

But that delays the feedback until runtime and if we can shorten a feedback loop we should. What if we could get it at compile time already?

It is not impossible and it will give us a even more fluent interface IDE-wise, so to speak.

By using a series of internal interfaces that the Builder class implements, we set up a chain of methods that guides the client.

The picture shows how this looks in IntelliJ and it will be similar in Eclipse and Netbeans. Notice that the “from” method returns the interface “ITo”. That interface has one method.

    public interface ITo {
        ISubject to(String to);
    }

Thus a chain is created where “from” returns “ITo” which method returns “ISubject” that has method that returns “IContent” that returns “IBuild”, the last interface. The latter has the job of handling the optional parameters and creation of the now correctly instantiated object. In this case the optional parameter is “mimeType”.

    public interface IBuild {
        IBuild mimeType(String mimeTypeName);

        EmailMessage build();
    }

The client code looks almost the same. We did not need to, but we skipped the “builder” method and hit the “from” method directly.  Since we are leaning on the language rules, the IDE tells us immediately which static method we should use.

        EmailMessage
                .from("gojko@example.com")
                .to("me@crisp.se")
                .subject("hello comrade")
                .content("Some content")
                .build();

Although the end result looks almost the same to the client, the feedback is more immediate and it is quicker to select one method than among several. You can no longer do this mistake:

        EmailMessage
                .from("gojko@example.com")
                .to("me@crisp.se")
                .subject("hello comrade")
                .from("Some content")            //compilation error
                .build();

So there is version 2 of the builder pattern for you. A bit more work for you when defining your classes but it is healthy to think about what is optional and what is not. And your clients will thank you. Not to mention when you must add another compulsory attribute. All client code will stop compiling which is so much better than crashing in runtime.

Here is the complete EmailMessage example. Enjoy your coding today!

@Data // Lombok
public class EmailMessage {

    private String from;
    private String to;
    private String subject;
    private String content;
    private String mimeType;  // optional

    private EmailMessage() {}

    public static ITo from(String from) {
        return new EmailMessage.Builder(from);
    }

    public interface ITo {
        ISubject to(String to);
    }

    public interface ISubject {
        IContent subject(String subject);
    }

    public interface IContent {
        IBuild content(String content);
    }

    public interface IBuild {
        IBuild mimeType(String mimeTypeName);

        EmailMessage build();
    }

    private static class Builder implements ITo, ISubject, IContent, IBuild {
        private EmailMessage instance = new EmailMessage();

        public Builder(String from) {
            instance.from = from;
        }

        public ITo from(String from) {
            instance.from = from;
            return this;
        }

        @Override
        public ISubject to(String to) {
            instance.to = to;
            return this;
        }

        @Override
        public IContent subject(String subject) {
            instance.subject = subject;
            return this;
        }

        @Override
        public IBuild content(String content) {
            instance.content = content;
            return this;
        }

        @Override
        public IBuild mimeType(String mimeTypeName) {
            instance.mimeType = mimeTypeName;
            return this;
        }

        @Override
        public EmailMessage build() {
            return instance;
        }
    }
}

8 Comments

  • 1
    Charles
    December 19, 2014 - 3:46 am | Permalink

    Really enjoy the “required fields” enhancement to the Builder pattern! I did change your ISubject and IContent names (I’ve never felt the “I” added any value) to RequiresSubject and RequiresContent, which I thought provided an even more readable hint from the IDE…

  • 2
    January 12, 2015 - 3:44 pm | Permalink

    http://www.roytuts.com/builder-pattern-in-jee-design-pattern/

  • 3
    Harry Bosch
    March 1, 2015 - 4:36 pm | Permalink

    Sweet.

  • 4
    April 22, 2015 - 1:01 pm | Permalink

    See also the step builder pattern here http://rdafbn.blogspot.ie/2012/07/step-builder-pattern_28.html

  • 5
    Marcelo
    June 1, 2015 - 5:20 pm | Permalink

    Thanks.

  • 6
    yyang
    August 12, 2015 - 8:55 pm | Permalink

    like

  • 7
    Jonas
    March 9, 2016 - 1:14 am | Permalink

    There is a capilization typo in this article that caused me a bit of confusion. Should be this instead: EmailMessage.Builder().from(“gojko@example.com”)

  • Leave a Reply

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