我必须用下面数百行代码来实现某些业务规则:
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)