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.
  }
}

现在,我可以验证两种不同类型的对象。这两个可能完全不同:假设我有一个 Store that is Validatable,然后一个Schedulewhich is 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 回答