复合策略模式 - java - 这段代码有多糟糕?

发布于 2024-07-22 06:49:31 字数 1930 浏览 8 评论 0原文

这个问题是我之前帖子的延续: 访问者模式实现在 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.
  }
}

现在,我可以验证两种不同类型的对象。 这两个可能完全不同:假设我有一个 Validatable 的 Store,然后有一个 ValidatableSchedule。 现在,如果我要编写一个如下所示的组合:

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 的想法。 你能建议我如何改进这个吗?

感谢你的帮助。

This question is kind of continuation to my earlier post: Visitor pattern implementation in java- How does this look?

I got a bit confused while refactoring my code. I am trying to convert my visitor pattern (explained in the prior post) into a composite strategy pattern. I am trying to do something like this:

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

Now, I would define a Rule like this:

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

Now, I could have two different types objects to be validated. These two could be completely different: Say I have a Store that is Validatable, and then a Schedule which is Validatable. Now, if I would write a composite that would look like this:

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();
  }
}

I would define an enum that defines what set of checks go where...

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
}

and finally, I would use it like this:

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

I have a strange feeling that my design is flawed. I am not liking the idea that my Rule interface expects a Validatable. Could you please suggest how I would improve this?

Appreciate your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦与时光遇 2024-07-29 06:49:31

当我第一次学习设计模式时,我一直在努力寻找使用它们的地方。 从那时起我就了解到过早的“模式化”有点像过早的优化。 首先,尝试以直接的方式进行,然后看看会给您带来什么问题。

尝试使用最少的接口和子类进行设计。 然后应用适合您发现的明显冗余的任何模式。 我从这篇文章和上一篇文章中得到的印象是,您可能过度构建了代码。

When I first learned about design patterns, I kept trying to find places to use them. I've since learned that premature "patternization" is kind of like premature optimization. First, try to do it in a straight-forward way, and then see what problems that gives you.

Try to design with minimal interfaces and subclassing. Then apply whatever pattern may be appropriate for the obvious redundancies you find. I get the impression from this and the previous post that you may be over-architecting your code.

再浓的妆也掩不了殇 2024-07-29 06:49:31

将 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 验证器(假设 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;
    }
}

或者,就像在您的示例中一样,我们可能有一个提供多种狗验证策略的枚举:

public enum DogValidationType implements ValidationStrategy<Dog> {
    STRATEGY_1 {
        public List<Rule<? super Dog>> getRules() {
            // answer rules...
        }
    },
    // more dog validation strategies
}

Replace Validatable by a generic type parameter T to make the validation framework type safe.

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

Let's extend our framework with an interface ValidationStrategy:

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

We are dealing with rules bounded by "? super T" so we can add a rule for Animal to a Dog Validator (assuming Dog extends Animal). The Validator now looks like this:

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

Now we can implement a sample DogValidationStrategy like this:

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

Or, like in your sample, we may have an Enum providing several dog validation strategies:

public enum DogValidationType implements ValidationStrategy<Dog> {
    STRATEGY_1 {
        public List<Rule<? super Dog>> getRules() {
            // answer rules...
        }
    },
    // more dog validation strategies
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文