1

目前我有这个实现了 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));username(String s)但是,据我所知,如果未在调用 Java 类中定义,则这不是有效的 Java 语法。我不想再重复整个AccountConstraint.Builder()过程来达到username(String s)部分。有什么解决办法吗?

第二个问题:可以AccountConstraint.getConstraints()改进还是写得更简单?

问候。

4

3 回答 3

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,返回一个ListorSet会比一个数组更好。

于 2013-06-29T13:16:29.460 回答
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;
}
于 2013-06-29T13:10:05.570 回答
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(...))

像这样定义约束(静态工厂方法而不是将它们添加到构建器)因此使它们易于组合。

于 2013-06-29T13:02:04.257 回答