8

この質問は、私の以前の投稿の一種です:javaでのビジターパターンの実装-これはどのように見えますか?

コードのリファクタリング中に少し混乱しました。ビジターパターン(前の投稿で説明)を複合戦略パターンに変換しようとしています。私はこのようなことをしようとしています:

public interface Rule {
  public List<ValidatonError> check(Validatable validatable);
}

ここで、次のようなルールを定義します。

public class ValidCountryRule  {
  public List<ValidationError> check(Validatable validatable) {
    // invokeDAO and do something, if violation met
    // add to a list of ValidationErrors.
    // return the list.
  }
}

これで、検証する2つの異なるタイプのオブジェクトを作成できます。これらの2つは完全に異なる可能性があります。あるストアがありValidatable、次にあるストアがScheduleあるとしValidatableます。さて、次のようなコンポジットを作成するとします。

class Validator implements Rule {
  private List<Rule> tests = new ArrayList<Rule>();

  public void addRule(Rule rule) {
    tests.add(rule);
  }

  public List<ValidationError> check(Visitable visitable) {
    List<ValidationError> list = new ArrayList<ValidationError>();
    for(Rule rule : tests) {
      list.addAll(rule.check(visitable);
    }
  }

  public Validator(ValidatorType type) {
    this.tests = type.getRules();
  }
}

enumどのチェックセットがどこに行くかを定義するを定義します...

public Enum ValidatorType {
  public abstract List<Rule> getRules();
  STORE_VALIDATOR {
    public List<Rule> getRules() {
      List<Rule> rules = new ArrayList<Rule>();
      rules.add(new ValidCountryRule());
      rules.add(new ValidXYZRule());
    }

  // more validators
}

そして最後に、私はそれを次のように使用します:

Validator validator = new Validator(ValidatorType.STORE_VALIDATOR);
for (Store store : stores) {
  validator.check(store);
}

デザインに欠陥があるのが不思議です。Ruleインターフェースがを期待しているという考えは好きではありませんValidatable。これをどのように改善するか提案していただけますか?

あなたの助けに感謝。

4

2 に答える 2

9

最初にデザイン パターンについて学んだとき、私はそれらを使用する場所を探し続けました。それ以来、時期尚早の「パターン化」は時期尚早の最適化に似ていることを学びました。まず、簡単な方法でそれを実行してみてください。次に、どのような問題が発生するかを確認してください。

最小限のインターフェイスとサブクラスで設計するようにしてください。次に、見つけた明らかな冗長性に適切なパターンを適用します。この記事と前回の投稿から、コードを過剰設計している可能性があるという印象を受けました。

于 2009-06-04T14:14:47.020 に答える
4

Validatable をジェネリック型パラメーター T に置き換えて、検証フレームワークを型安全にします。

public interface Rule<T> {
    public List<ValidationError> check(T value);
}

インターフェイス ValidationStrategy を使用してフレームワークを拡張しましょう。

public interface ValidationStrategy<T> {
    public List<Rule<? super T>> getRules();
}

"? super T" で区切られたルールを扱っているので、Animal のルールを Dog Validator に追加できます (Dog が Animal を拡張すると仮定)。バリデーターは次のようになります。

public class Validator<T> implements Rule<T> {
    private List<Rule<? super T>> tests = new ArrayList<Rule<? super T>>();

    public Validator(ValidationStrategy<T> type) {
        this.tests = type.getRules();
    }

    public void addRule(Rule<? super T> rule) {
        tests.add(rule);
    }

    public List<ValidationError> check(T value) {
        List<ValidationError> list = new ArrayList<ValidationError>();
        for (Rule<? super T> rule : tests) {
            list.addAll(rule.check(value));
        }
        return list;
    }
}

これで、サンプルの DogValidationStrategy を次のように実装できます。

public class DogValidationStrategy implements ValidationStrategy<Dog> {
    public List<Rule<? super Dog>> getRules() {
        List<Rule<? super Dog>> rules = new ArrayList<Rule<? super Dog>>();
        rules.add(new Rule<Dog>() {
            public List<ValidationError> check(Dog dog) {
                // dog check...
                return Collections.emptyList();
            }
        });
        rules.add(new Rule<Animal>() {
            public List<ValidationError> check(Animal animal) {
                // animal check...
                return Collections.emptyList();
            }
        });
        return rules;
    }
}

または、サンプルのように、いくつかの犬の検証戦略を提供する Enum がある場合があります。

public enum DogValidationType implements ValidationStrategy<Dog> {
    STRATEGY_1 {
        public List<Rule<? super Dog>> getRules() {
            // answer rules...
        }
    },
    // more dog validation strategies
}
于 2009-06-07T16:24:23.593 に答える