我正在尝试使用Builder Pattern作为我的下层类。最初我使用我的类的构造函数来设置所有参数但不小心我遇到了Builder模式,它看起来很适合我的用例。
以下是我的课程,其中人们将主要通过userId
,clientId
和parameterMap
,但其他字段是可选的,他们可能会或可能不会通过它。而且如果他们没有传递任何超时值,我需要将默认超时值设置为500,但如果他们传递任何超时值,那么它应该覆盖我的默认超时值。这里的首选项是一个有四个字段的ENUM。
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
}
下面是我最初使用如何通过将参数传递给构造函数来构造ModelInput
对象的示例。最初我传递了所有参数,但客户端大多会传递userId
,clientId
和parameterMap
,其他字段是可选的。
Map<String, String> paramMap = new HashMap<String, String>();
paramMap.put("attribute", "segmentation");
ModelInput input = new ModelInput(109739281L, 20L, Preference.SECONDARY, paramMap, 1000L, true);
如何将上面的代码转换为开始使用生成器模式,正如Bloch在Effective Java中所说的那样,它也是线程安全且不可变的?
如何使用Builder模式对此进行验证检查?有可能人们可以传递userId零或负数与客户端ID和超时相同,也可以与地图相同。
答案 0 :(得分:2)
我不熟悉你所引用的那本书,但我建议你阅读post of wikipedia regarding the Builder pattern这本书很简单。
实施可能是:
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;
}
...
}
然后,当您想要初始化对象时,您可以调用
ModelInput model = new ModelInput.Builder(...).build();
关于验证过程,它与检查值(在构造函数中或build
方法中)基本相同。
希望我帮忙!
答案 1 :(得分:2)
构建器构造函数必须具有必需参数。所以,在你的情况下,如果userId,clientId和parameterMap是强制性的,我们会有类似的东西:
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
}
这是如何使用您的构建器类:
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();
希望这会有所帮助:)
答案 2 :(得分:0)
试试这个
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,...
}
}
}
答案 3 :(得分:0)
添加其他人写的内容:
为了使您的类不可变,您还需要使parameterMap变量不可变。您可以在实例化ModelInput类时执行此操作:
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;
}
请注意使用Collections.unmodifiablemap();
您还需要使您的Preference实例不可变,或至少让它知道它实际上不不可变。