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)。解決策はありますか?

2 番目の質問:AccountConstraint.getConstraints()改善したり、より簡単に記述したりできますか?

よろしく。

4

3 に答える 3

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 に答える