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

43

我必须实现数百行以下代码的某些业务规则:

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

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

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>

1
你能提供一些 if else 语句的示例吗?它们之间有什么相似之处吗? - stinepike
状态模式的使用? - Fendy
3
我认为可以在这里使用“责任链”模式:http://www.oodesign.com/chain-of-responsibility-pattern.html - Marco Forberg
6个回答

31

你应该查看规则设计模式 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


您还可以查看一篇博客文章,其中解释了规则设计模式的工作原理http://www.michael-whelan.net/rules-design-pattern/ - mavi

11

以下是有关编程的内容翻译成中文:我有编辑我的问题以包含条件逻辑示例。我在一个类的某些属性上有条件逻辑来实现规则一,而另一些属性(可能包括在规则一中使用的一些属性)则用于规则二。 - SCoder

6
你可以使用命令模式工厂模式命令模式可用于替换繁琐的开关/ 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/switch语句放入一个工厂中,由该工厂处理丑陋的代码并隐藏大量的条件判断。 工厂模式示例代码

1
谢谢提供信息。您能否提供一些示例,说明这些模式如何帮助减少 if/else 语句的使用。 - SCoder
看起来是个不错的例子,但可能不符合我的要求。我已经编辑了我的问题,包括条件逻辑的一个示例。我有一些类属性的条件逻辑适用于规则一,另外一些属性(可能包括规则一中使用的一些属性)适用于规则二。 - SCoder
2
请给原始答案以功劳:):https://dev59.com/h3M_5IYBdhLWcg3w2XHw - Dherik

3

有一个可能有用的东西是规则引擎,比如Drools。虽然它不是一种设计模式,所以这可能不是你要找的答案。但是,在我看来,你应该考虑使用它。这里有一篇关于何时使用规则引擎的优秀文章


谢谢,但我的要求是不使用任何规则引擎,因为项目需要 :( ,所以我正在寻找一些设计模式。 - SCoder
我同意tieTYT的观点。规则引擎是实现BRs的完美选择。根据我的个人经验,它可以生成非常干净且易于维护的代码,并将开发时间缩短数倍。 - Kingz

1
一个使用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)

1
设计模式可以帮助您使代码更易读或提高其可维护性,但如果您确实需要评估如此多的条件,则无法避免IF语句。我会考虑从其他角度看问题(例如:我真的需要一百个条件语句来解决问题吗?)并尝试更改或改进算法。
表达式语言可能会提供一些帮助,因为您可以通过此工具编程创建表示每个IF语句的字符串,并评估结果,但您仍然必须解决与每个条件关联的特定逻辑执行相关的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接