开发者

Is there a Java design pattern for the problem I am trying to solve?

开发者 https://www.devze.com 2023-04-04 23:39 出处:网络
I have a data model which contains an array of Product objects. Before reporting from this model I am required to run a set of rules which check the integrity of each Product object in the model. One

I have a data model which contains an array of Product objects. Before reporting from this model I am required to run a set of rules which check the integrity of each Product object in the model. One way I can think of doing this is to have a Rule interface e.g.

public interface CheckRule {
    boolean runRule(Product p);
}

For each rule I can then have a separate Rule class which implements the CheckRule interface. I can then have a double loop to run all the rules e.g.:

for (Product p : Products) {
   for (Rule r : Rules) {
      if (! r.runRule(p) {
              // report on the broken rule
      }
   }
}

If I have hundreds of rules however I end up with hundreds of Rule classes, which seems a messy way to do it. An alternative is to have a single RuleManager class, which has a separate method for each ru开发者_StackOverflow中文版le e.g.

public class RuleManager {

    boolean runRule1(Product p) { // rule 1 logic}

    boolean runRule2(Product p) { // rule 2 logic}

    boolean runRule3(Product p) { // rule 3 logic}

    etc...
}

This reduces the number of classes, but means that I end up with a single class with hundreds of methods. Both methods feel wrong to me, and I was wondering if there is a Design Pattern which covers this scenario which I could use instead?


The Specification Design Pattern may solve your problem.

http://en.wikipedia.org/wiki/Specification_pattern


Pattern? Frameworks...

E.g.

  • JSR303 - bean validation -> Hibernate Validator
  • Rules engine -> Drools


Look up Java Validation API:

http://www.infoq.com/news/2010/03/javaee6-validation

It comes with tons of already build validators that you can use by simply addnotating your bean properties with certain annotations (such as @ZipCode and @NotNull), and it let's you easily declare custom validators and what you want them to validate, and you have all the scaffolding already there.


I think you'll find that you can often parameterize rules, so that you won't need anywhere near one class per rule. This is especially true if you're willing to consider using reflection.

JSR303, aka Java Validation API, is good for simple field validation, but rapidly runs out of steam when you need to do more complex stuff.

Drools is not relevant, if I understand the use case - way too heavy.

Think carefully about how to handle validation errors. You want to be able to report multiple errors - don't bail out on the first one, your users will hate you. So you probably want to have some kind of error collector object that the validators put the errors in, that is then returned by the validator framework.


Having rules as separate classes seems better. Organize them into a meaningful package hierarchy to ease mental burden.

Bundling many validation methods into a single class will make that class heavy. Eventually you would like to split that class into multiple classes, with a single entry point per class (and possibly passing a validation callback which reveives notifications about failed rules). But then it would be nice to make the single rules hidden from the outside world, which makes testing hard.


Basically, when you have a collection of objects(in your case collection of Products) which require a set of operation to be done on them(in your case to check integrity on each Product) you have to use Visitor pattern. Standart implementation of pattern reqiures one operation for each Product type(I assume that you have seperate class for each product type). But as stated earlier you may somehow reduce the number of methods performing subclassing in Product hierarchy and specifying some parameter for some branches of that hierarchy tree.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号