Updated: Questions on implementing Builder design pattern I am in the process of using Java Builder design pattern to write a connector class that has optional member variables and need some suggestions. My question from here Standard practices for employing Java Builder design pattern has been updated and the code now presented is not psuedocode but is specific.

public class Connector {

    // Instance variables
    String appUrl = null;
    String oneTimePwd = null;
    String accessKey = null;

    // Private constructor
    private Connector(Builder builder) {
        this.appUrl = builder.appUrl;
        this.accessKey = builder.accessKey;
        this.oneTimePwd = builder.oneTimePwd;
    }

    public static class Builder {

        // Instance variables
        String appUrl = null;
        String accessKey = null;
        String oneTimePwd = null;

        public Builder() {
            // Empty constructor that accepts no arguments.
        }

        // Setter method for mandatory field/s
        public Builder setMandatoryParameters(String appUrl) {
            this.appUrl = appUrl;
            return this;
        }

        // Setter method1 for optional field/s
        public Builder setAccessKey(String accessKey) {
            this.accessKey = accessKey;
            return this;
        }

        // Setter method2 for optional field/s
        public Builder setOneTimePwd(String oneTimePwd) {
            this.oneTimePwd = oneTimePwd;
            return this;
        }

        public Connector Build() {
            if (accessKey != null) {
                return new Connector(this);
            } else if (oneTimePwd != null) {
                return new Connector(this);
            } else {
                // log.error("Either Access key or One time password must be specified.")
            }
            return null;
        }
    }

    // Other methods of the Connector class
    // ...
}


Question 1:
Is it sensible to make use of a method "setMandatoryParameters()" to obtain values for mandatory parameters? This will allow creation of an instance of the Builder without supplying the mandatory parameters which can be a drawback. Is it much better to ask the user to supply the values for mandatory parameters with Builder's constructor?

Question 2:
Either access key or one time password is needed to establish a successful connection. Thus, field validations such as null checks have been employed in the "Build()" method. Should such validations be performed in the Connector class's constructor instead?
Question 1: If the parameters are mandatory anyway you might as well enforce this through your API. This reads just fine:

Connector con = new Connector.Builder(mandatoryURL)
                    .setAccessKey(key)
                    .build();


Question 2: Either place, since you contained the checks entirely in the Connector class (because of the private constructor) you have full control anyway.

Since either one of them is mandatory and you I'm assuming you won't use both of them, you might also provide 2 separate "build" methods that take one of those parameters as input.

public static class Builder {
    String appUrl = null;

    public Builder(String appUrl) {
        this.appUrl = appUrl;
    }

    public Connector withAccessKey(String accessKey) {
        Connector result = new Connector(appUrl);
        connector.accessKey = accessKey;
        return connector;
    }

    public Connector withOneTimePwd(String oneTimePwd) {
        Connector result = new Connector(appUrl);
        connector.oneTimePwd = oneTimePwd;
        return connector;
    }
}


Quick note that I changed the Connector constructor to also take the URL parameter instead of the builder. Your way works just fine in this case, I just prefer to have the builder be responsible for setting the correct fields instead of making the Connector "know" about the Builder class.



Alternative solution to using a Builder is to use factory methods. Your Connector class could then look something like this:

public class Connector {

    String appUrl = null;
    String oneTimePwd = null;
    String accessKey = null;

    private Connector(String appUrl) {
        this.appUrl = appUrl;
    }

    public static Connector createWithAccessKey(String appUrl, String accessKey) {
        Connector result = new Connector(appUrl);
        connector.accessKey = accessKey;
        return connector;
    }

    public static Connector createWithOneTimePwd(String appUrl, String oneTimePwd) {
        Connector result = new Connector(appUrl);
        connector.oneTimePwd = oneTimePwd;
        return connector;
    }

    //... rest of the class
}


You can now use it as follows:

Connector con = Connector.createWithAccessKey(someUrl, myKey);


This has about the same effect as your Builder idea but with a lot less boilerplate code to reach it.