How to use Builder pattern as described by Joshua Bloch's version in my ModelInput class?

做~自己de王妃 提交于 2019-12-02 09:43:55

问题


I am trying to use Builder Pattern for my below class.. Initially I was using constructor of my class to set all the parameters but accidentally I came across Builder pattern and it is looking good for my use case.

Below is my class in which people will mostly pass userId, clientId and parameterMap always but other fields are optional and they may or may not pass it. And also if they are not passing any timeout value, I need to have default timeout value set as 500 always but if they are passing any timeout value then it should override my default timeout value. Here Preference is an ENUM having four fields.

public final class ModelInput {

    private long userid;
    private long clientid;
    private long timeout = 500L;
    private Preference pref;
    private boolean debug;
    private Map<String, String> parameterMap;

    public ModelInput(long userid, long clientid, Preference pref, Map<String, String> parameterMap, long timeout, boolean debug) {
        this.userid = userid;
        this.clientid = clientid;
        this.pref = pref;
        this.parameterMap = parameterMap;
        this.timeout = timeout;
        this.debug = debug;
    }

 ... //getters here
}    

Below is an example how I was using initially to construct ModelInput object by passing parameters to constructor. Initially I was passing all the parameters but clients will mostly pass userId, clientId and parameterMap always and other fields are optional..

Map<String, String> paramMap = new HashMap<String, String>();
paramMap.put("attribute", "segmentation");

ModelInput input = new ModelInput(109739281L, 20L, Preference.SECONDARY, paramMap, 1000L, true);

How do I convert my above code to start using Builder pattern as told by Bloch's in Effective Java which is also thread safe and immutable as well?

And how can I do the validation check as well on this using Builder pattern? It might be possible people can pass userId zero or negative numbers same with client id and timeout and same with map as well..


回答1:


Builder constructor must have the mandatory parameters. So, in your case, if userId, clientId and parameterMap are mandatory, we will have something like that:

public final class ModelInput {

    private long userid;
    private long clientid;
    private long timeout = 500L;
    private Preference pref;
    private boolean debug;
    private Map<String, String> parameterMap;

    public ModelInput(Builder builder) {
        this.userid = builder.userId;
        this.clientid = builder.clientId;
        this.pref = builder.preference;
        this.parameterMap = builder.parameterMap;
        this.timeout = builder.timeout;
        this.debug = builder.debug;
    }

    public static class Builder {
        private long userId;
        private long clientId;
        private Preference preference;
        private boolean debug;
        private Map<String, String> parameterMap;

        public Builder(long userId, long clientId, Map<String, String> parameterMap) {
            this.userId = userId;
            this.clientId = clientId;
            this.parameterMap = parameterMap;
        }

        public Builder preference(Preference preference) {
            this.preference = preference;
            return this;
        }

        public Builder debug(boolean debug) {
            this.debug = debug;
            return this;
        }

        public Builder timeout(long timeout) {
            this.timeout = timeout;
            return this;
        }

        ...

        public ModelInput build() {
            return ModelInput(this);
        }
    }

    // ModelInput getters / setters
}

And this is how to use your builder class:

String paramMap = new HashMap<String, String>();
paramMap.put("attribute", "segmentation");

ModelInput.Builder builder = new ModelInput.Builder(109739281L, 20L, paramMap);
builder.preference(Preference.SECONDARY).timeout(1000L).debug(true);

ModelInput modelInput = builder.build();

Hope this helps :)




回答2:


I am not familiar with the book you are referencing, but I would suggest reading the post of wikipedia regarding the Builder pattern which is rather straight forward.

An implementation could be:

public final class ModelInput {

...

    public static class Builder {
        private long userid;
        ...    

        public Builder(long userid) {
            this.userid = userid;
        }

       ...

        public ModelInput build() {
            return new ModelInput(this);
        }
    }

    private ModelInput(Builder builder){
        this.userid = builder.userid;
        this.clientid = builder.clientid;
        this.pref = builder.pref;
        this.parameterMap = builder.parameterMap;
        this.timeout = builder.timeout;
        this.debug = builder.debug;
    }

...
}

Then when you want to initialize an object, you would call

ModelInput model = new ModelInput.Builder(...).build();

Regarding the validation process, it would be essentially the same as it would be made by checking the values (either in the constructor, or in the build method).

Hope I helped!




回答3:


try this

public final class ModelInput {
    ...

    public static class Builder {
        private long userid;
        ...

        public Builder setUserId(long userId) {
            this.userId = userId;
        }
        ...

        public ModelInput build() {
            return new ModelInput(userId,...
        }
    }
}  



回答4:


To add to what the others have written:

In order to make your class immutable, you need to make parameterMap variable immutable as well. You can do that when the ModelInput class is instantiated:

private ModelInput(Builder builder){
  this.userid = builder.userid;
  this.clientid = builder.clientid;
  this.pref = builder.pref;
  this.parameterMap = Collections.unmodifiableMap(builder.parameterMap);
  this.timeout = builder.timeout;
  this.debug = builder.debug;
}

Notice the use of Collections.unmodifiablemap();

You'll also need to make your Preference instance immutable, or at least make it known that it is in fact not immutable.



来源:https://stackoverflow.com/questions/21040771/how-to-use-builder-pattern-as-described-by-joshua-blochs-version-in-my-modelinp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!