2017-06-19 12:02
(以下是自己瞎琢磨的,兴许早就有人这么干了。)
我们要解决这样一个问题:
假设你在用 Builder 模式来创建一个对象,比如这样:
User user = new User.Builder()
.username("test_account")
.email("test@example.com")
.build();
这时你希望:只有当输入的 email 是一个有效的邮件地址时,才设置这一项;否则就忽略 email。通常我们会这样修改代码:
User.Builder builder = new User.Builder()
.username("");
if (isValidEmail(emailStr)) {
builder.email(emailStr);
}
User user = builder.build();
这样当然没什么不好。但是如果你特别喜欢一条链解决问题,其实也有办法保持链条不断。
第一个办法是使用三目运算符。在 Builder 方法支持的前提下,你可以写:
builder
.email(isValidEmail(emailStr) ? emailStr : "") // 或者 null
但是有时候 Builder 不希望你叫 email(“”) 或者 email(null)。Builder 希望你忽略这项设置,甚至可能要求你做一些其他操作(比如记录这个错误事件等等),总之三目运算符搞不定。这个时候你的另一个选择是:在 Builder 里创建一个 if-then 环节。
你要做的只是在 Builder 中加入以下方法:
public Builder ifThen(boolean condition, Function<Builder, Void> statement) {
if (condition) {
statement.apply(this);
}
return this;
}
然后你就可以这么调用:
User user = new User.Builder()
.username("test_account")
.ifThen(isValidEmail(emailStr), builder -> {
builder.email(emailStr);
return null;
})
.build();
这样就实现了与上面第二段代码完全等价的操作,同时避免生成 Builder 对象。好处主要是易读性方面,逻辑链清晰。不过也许有人喜欢上面第二段代码那样简单直接,见仁见智吧。
还可以进一步扩展为 if-then-else 操作:
public Builder ifThenElse(
boolean condition,
Function<Builder, Void> thenStatement,
@Nullable Function<Builder, Void> elseStatement) {
if (condition) {
thenStatement.apply(this);
} else if (elseStatement != null) {
elseStatement.apply(this);
}
return this;
}