我最近开始在我的一个项目中使用 Builder 模式,我正在尝试在我的 Builder 类上添加某种验证。我假设我们不能在编译时执行此操作,这就是我在运行时进行此验证的原因。但可能是我错了,这就是我想看看我是否可以在编译时做到这一点。
传统建造者模式
public final class RequestKey {
private final Long userid;
private final String deviceid;
private final String flowid;
private final int clientid;
private final long timeout;
private final boolean abcFlag;
private final boolean defFlag;
private final Map<String, String> baseMap;
private RequestKey(Builder builder) {
this.userid = builder.userid;
this.deviceid = builder.deviceid;
this.flowid = builder.flowid;
this.clientid = builder.clientid;
this.abcFlag = builder.abcFlag;
this.defFlag = builder.defFlag;
this.baseMap = builder.baseMap.build();
this.timeout = builder.timeout;
}
public static class Builder {
protected final int clientid;
protected Long userid = null;
protected String deviceid = null;
protected String flowid = null;
protected long timeout = 200L;
protected boolean abcFlag = false;
protected boolean defFlag = true;
protected ImmutableMap.Builder<String, String> baseMap = ImmutableMap.builder();
public Builder(int clientid) {
checkArgument(clientid > 0, "clientid must not be negative or zero");
this.clientid = clientid;
}
public Builder setUserId(long userid) {
checkArgument(userid > 0, "userid must not be negative or zero");
this.userid = Long.valueOf(userid);
return this;
}
public Builder setDeviceId(String deviceid) {
checkNotNull(deviceid, "deviceid cannot be null");
checkArgument(deviceid.length() > 0, "deviceid can't be an empty string");
this.deviceid = deviceid;
return this;
}
public Builder setFlowId(String flowid) {
checkNotNull(flowid, "flowid cannot be null");
checkArgument(flowid.length() > 0, "flowid can't be an empty string");
this.flowid = flowid;
return this;
}
public Builder baseMap(Map<String, String> baseMap) {
checkNotNull(baseMap, "baseMap cannot be null");
this.baseMap.putAll(baseMap);
return this;
}
public Builder abcFlag(boolean abcFlag) {
this.abcFlag = abcFlag;
return this;
}
public Builder defFlag(boolean defFlag) {
this.defFlag = defFlag;
return this;
}
public Builder addTimeout(long timeout) {
checkArgument(timeout > 0, "timeout must not be negative or zero");
this.timeout = timeout;
return this;
}
public RequestKey build() {
if (!this.isValid()) {
throw new IllegalStateException("You have to pass at least one"
+ " of the following: userid, flowid or deviceid");
}
return new RequestKey(this);
}
private boolean isValid() {
return !(TestUtils.isEmpty(userid) && TestUtils.isEmpty(flowid) && TestUtils.isEmpty(deviceid));
}
}
// getters here
}
问题陈述:
如您所见,我有各种参数,但只有一个参数clientId
是必需的,其余参数是可选的。userid
在我上面的代码中,我需要设置flowid
或deviceid
设置。如果这三个都没有设置,那么我将抛出IllegalStateException
一条错误消息,如代码中所示。如果设置了所有三个或两个,那很好,我正在对这三个或两个做一些优先逻辑来决定使用哪一个,但至少必须设置其中一个。
并不强制他们每次都通过所有三个 id,他们可以通过所有三个或有时两个或有时只通过一个,但条件是应该设置其中之一。
我正在寻找的是 - 除了在运行时做所有这些事情之外,我可以在编译时执行此操作并且不构建我的构建器模式,除非这三个设置中的任何一个并且在编译时它应该告诉丢失了什么?
我发现了这个 SO链接,它完全谈论同一件事,但不确定如何在我的场景中使用它?还有这个带有扭曲的构建器模式和这个SO问题