在我们的项目中,我们使用布尔运算符实现了规范模式(参见DDD第274页),如下所示:
public abstract class Rule { public Rule and(Rule rule) { return new AndRule(this, rule); } public Rule or(Rule rule) { return new OrRule(this, rule); } public Rule not() { return new NotRule(this); } public abstract boolean isSatisfied(T obj); } class AndRule extends Rule { private Rule one; private Rule two; AndRule(Rule one, Rule two) { this.one = one; this.two = two; } public boolean isSatisfied(T obj) { return one.isSatisfied(obj) && two.isSatisfied(obj); } } class OrRule extends Rule { private Rule one; private Rule two; OrRule(Rule one, Rule two) { this.one = one; this.two = two; } public boolean isSatisfied(T obj) { return one.isSatisfied(obj) || two.isSatisfied(obj); } } class NotRule extends Rule { private Rule rule; NotRule(Rule obj) { this.rule = obj; } public boolean isSatisfied(T obj) { return !rule.isSatisfied(obj); } }
使用方法链接可以很好地表达规则,但它不支持标准的运算符优先级规则 导致微妙的错误。
以下规则不相同:
Rule<Car> isNiceCar = isRed.and(isConvertible).or(isFerrari); Rule<Car> isNiceCar2 = isFerrari.or(isRed).and(isConvertible);
如果汽车不是敞篷汽车,那么规则 isNiceCar2 就不满意了,因为如果它们是布尔值,这可能会让人感到困惑
isRed && isConvertible || isFerrari等同于{{2} }
我意识到如果我们将isNiceCar2重写为isFerrari.or(isRed.and(isConvertible)),它们将是等价的,但两者在语法上都是正确的。
我们可以提出的最佳解决方案是取消方法链,并改为使用构造函数:
isFerrari || isRed && isConvertible
有人有更好的建议吗?
答案 0 :(得分:2)
你的“构造函数”解决方案听起来是正确的(至少在语义上),因为它强制构建更接近表达式树而不是链的东西。另一个解决方案是将评估功能从规则实现中拉出来,这样就可以强制执行优先级(通过遍历链)。