目前我有这个实现Builder模式的类,为了便于阅读,我选择省略一些方法,更准确地说,我只显示username
的构建方法。
package dao.constraint;
import java.util.Arrays;
public class AccountConstraint {
private Constraint<Range<Integer>> accountIdConstraint;
private Constraint<String> usernameConstraint;
private Constraint<String> passwordConstraint;
private Constraint<String> emailConstraint;
private AccountConstraint(Builder builder) {
this.accountIdConstraint = builder.accountIdConstraint;
this.usernameConstraint = builder.usernameConstraint;
this.passwordConstraint = builder.passwordConstraint;
this.emailConstraint = builder.emailConstraint;
}
public Constraint<Range<Integer>> getAccountIdConstraint() {
return accountIdConstraint;
}
public Constraint<String> getUsernameConstraint() {
return usernameConstraint;
}
public Constraint<String> getPasswordConstraint() {
return passwordConstraint;
}
public Constraint<String> getEmailConstraint() {
return emailConstraint;
}
public Constraint[] getConstraints() {
return Arrays.asList(this.getAccountIdConstraint(), this.getUsernameConstraint(), this.getPasswordConstraint(), this.getEmailConstraint()).toArray(new Constraint[4]);
}
public static class Builder {
private Constraint<Range<Integer>> accountIdConstraint;
private Constraint<String> usernameConstraint;
private Constraint<String> passwordConstraint;
private Constraint<String> emailConstraint;
public Builder() {
this.accountIdConstraint = null;
this.usernameConstraint = null;
this.passwordConstraint = null;
this.emailConstraint = null;
}
public Builder username(final String username) {
this.usernameConstraint = new Constraint<>(Operation.IS, true, username, "username");
return this;
}
public Builder notUsername(final String username) {
this.usernameConstraint = new Constraint<>(Operation.IS, false, username, "username");
return this;
}
public Builder usernameLike(final String username) {
this.usernameConstraint = new Constraint<>(Operation.LIKE, true, username, "username");
return this;
}
public Builder usernameNotLike(final String username) {
this.usernameConstraint = new Constraint<>(Operation.LIKE, false, username, "username");
return this;
}
public AccountConstraint build() {
return new AccountConstraint(this);
}
}
}
正如您所看到的,AccountConstraint.Builder.username(String s)
和AccountConstraint.Builder.notUsername(String s)
之间存在非常微妙的差异。
我希望能够写出new AccountConstraint.Builder().not(username(s));
之类的内容。但是,据我所知,如果在调用Java类中未定义username(String s)
,则这不是有效的Java语法。我不想再重复整个AccountConstraint.Builder()
以达到username(String s)
部分。任何解决方案?
第二个问题:AccountConstraint.getConstraints()
可以改进或写得更简单吗?
问候。
答案 0 :(得分:2)
在这种情况下,我发现非常优雅的是使用静态工厂方法编写实用程序类,如。
public static Constraint userName(...) { ... }
和import static blabla.Utility.username;
然后,您可以在java中编写几乎声明性的人类可读查询。这与用于单元测试的hamcrest库非常相似,您可以在其中编写类似的内容。
Assert.assertThat(blabla, is(equalTo(nullValue()));
在这种情况下,Not
应该实现Constraint
并且只是否定嵌套(引用)约束,如下所示:
public static Constraint not(Constraint negated) { return new Not(negated); }
这导致代码如
PreparedStatement ps = new QueryBuilder()
.select()
.from(table("accounts")
.where(not(username(equalTo("blabla")))
.compile();
您可以为布尔组合添加静态工厂:
.where(and(
.not(...),
.not(or(...))
定义这样的约束(静态工厂方法而不是将它们添加到构建器中)因此使它们易于组合。
答案 1 :(得分:2)
你可以使not
成为构建器的一个方法,设置一个标志,然后否定下一个约束。
private boolean negate = false;
public Builder not() {
negate = true;
}
public Builder username(final String username) {
this.usernameConstraint = new Constraint<>(Operation.IS, !negate, username, "username");
negate = false;
return this;
}
答案 2 :(得分:2)
关于你的第二个问题:
public Constraint[] getConstraints() {
return Arrays.asList(this.getAccountIdConstraint(),
this.getUsernameConstraint(),
this.getPasswordConstraint(),
this.getEmailConstraint())
.toArray(new Constraint[4]);
}
可以重写为:
public Constraint[] getConstraints() {
return new Constraint[] {
this.accountIdConstraint,
this.usernameConstraint,
this.passwordConstraint,
this.emailConstraint
};
}
但IMO,返回List
或Set
会比数组好。