在java中用数百个if else实现业务规则的设计模式



我必须用下面数百行代码来实现某些业务规则:

if this
      then this
else if
      then this
.
. // hundreds of lines of rules
 else
      that

我们是否有任何设计模式可以有效地实现这一点或重用代码,以便它可以应用于所有不同的规则?我听说过规范模式,它创建了如下内容:

public interface Specification {
boolean isSatisfiedBy(Object o);
Specification and(Specification specification);
Specification or(Specification specification);
Specification not(Specification specification);
}

public abstract class AbstractSpecification implements Specification {
public abstract boolean isSatisfiedBy(Object o);
public Specification and(final Specification specification) {
 return new AndSpecification(this, specification);
}
public Specification or(final Specification specification) {
 return new OrSpecification(this, specification);
}
 public Specification not(final Specification specification) {
 return new NotSpecification(specification);
}
}

然后实现Is, And, Or方法,但我认为这不能拯救我从写if-else(也许我的理解是不正确的)…

是否有最好的方法来实现这样的业务规则有这么多的if-else语句?

编辑:只是一个示例。A、B、C等是类的属性。除了这些,还有很多类似的规则。我想为此创建一个通用代码。

    If <A> = 'something' and <B> = ‘something’ then
    If <C> = ‘02’ and <D> <> ‘02’ and < E> <> ‘02’  then
        'something'
    Else if <H> <> ‘02’ and <I> = ‘02’ and <J> <> ‘02’  then
        'something'
    Else if <H> <> ‘02’ and <I> <> ‘02’ and <J> = ‘02’  then
        'something'
    Else if <H> <> ‘02’ and <I> = ‘02’ and <J> = ‘02’  then 
        'something'
    Else if <H> = ‘02’ and <I> = ‘02’ and <J> <> ‘02’  then 
        'something'
    Else if <H> = ‘02’ and <I> <> ‘02’ and <J> = ‘02’  then 
        'something'
    Else if <H> = ‘02’ and <I> = ‘02’ and <J> = ‘02’  then:
        If <Q> = Y then
            'something'
        Else then 
            'something'
Else :
Value of <Z>

您应该查看规则设计模式http://www.michael-whelan.net/rules-design-pattern/。它看起来与您给出的示例代码非常相似,由一个基本接口组成,该接口定义了确定是否满足规则的方法,然后是每个不同规则的各种具体实现。根据我的理解,你的switch语句会变成某种简单的循环,它只会评估东西,直到你的规则组合满足或失败。

interface IRule {
    bool isSatisfied(SomeThing thing);
}
class RuleA: IRule {
    public bool isSatisfied(SomeThing thing) {
        ...
    }
}
class RuleB: IRule {
    ...
}
class RuleC: IRule {
    ...
}

构成规则:

class OrRule: IRule {
    private readonly IRule[] rules;
    public OrRule(params IRule[] rules) {
        this.rules = rules;
    }
    public isSatisfied(thing: Thing) {
        return this.rules.Any(r => r.isSatisfied(thing));
    }
}
class AndRule: IRule {
    private readonly IRule[] rules;
    public AndRule(params IRule[] rules) {
        this.rules = rules;
    }
    public isSatisfied(thing: Thing) {
        return this.rules.All(r => r.isSatisfied(thing));
    }
}
// Helpers for AndRule / OrRule
static IRule and(params IRule[] rules) {
    return new AndRule(rules);
}
static IRule or(params IRule[] rules) {
    return new OrRule(rules);
}

在某个事物上运行规则的某个服务方法:

class SomeService {
        public evaluate(IRule rule, Thing thing) {
            return rule.isSatisfied(thing);
        }
    }

用法:

// Compose a tree of rules
var rule = 
    and (
        new Rule1(),
        or (
            new Rule2(),
            new Rule3()
        )
    );
var thing = new Thing();
new SomeService().evaluate(rule, thing);

这里也有答案:https://softwareengineering.stackexchange.com/questions/323018/business-rules-design-pattern

策略模式在这里可能很有用。请勾选"用策略替换条件逻辑"

可以使用命令模式工厂模式

命令模式可以用来代替繁琐的switch/if块,这些块往往会随着添加新选项而无限增长。

public interface Command {
     void exec();
}
public class CommandA() implements Command {
     void exec() {
          // ... 
     }
}
// etc etc

然后构建一个Map<String,Command>对象并用Command实例填充它:

commandMap.put("A", new CommandA());
commandMap.put("B", new CommandB());

则可以将if/else if链替换为:

commandMap.get(value).exec();

工厂模式中,你将if/开关包含在一个工厂中,该工厂负责处理丑陋并隐藏大量的if。工厂模式示例代码.

像Drools这样的规则引擎可能会有所帮助。但它不是一种设计模式,所以这可能不是您要寻找的答案。但在我看来,你应该考虑一下。这里有一篇关于何时应该使用规则引擎的好文章。

设计模式可以帮助您使代码更具可读性或提高其可维护性,但是如果您确实需要评估如此多的条件,则无法避免使用if语句。

我会考虑从另一个角度看问题(例如:我真的需要100个条件语句来解决问题吗?),我会尝试改变或改进算法。

表达式语言可以提供一些帮助,因为您可以通过编程方式创建表示每个IF语句的字符串,并使用该工具计算结果,但是您仍然必须解决与每个条件相关的特定逻辑的执行相关的问题。

一个简单的python策略演示:

class Context(object):
  def __init__(self, strategy):
    self.strategy = strategy
  def execute(self, num1, num2):
    return self.strategy(num1, num2)
class OperationAdd(object):
  def __call__(self, num1, num2):
    return num1 + num2

class OperationSub(object):
  def __call__(self, num1, num2):
    return num1 - num2

if __name__ == '__main__':
  con = Context(OperationAdd())
  print "10 + 5 =", con.execute(10, 5)
  con = Context(OperationSub())
  print "10 - 5 =", con.execute(10, 5)

最新更新