规则匹配需求:
规则包括相等、不等、正则匹配、包含、不含、为空、不空、大于、小于、区间等等
数据类型包括字符串、数值型(整形、长整型、浮点数)、时间型(绝对时间、相对时间)
获取一条记录,提取其中某个字段,根据字段类型,与给定的值根据规则进行判定,满足返回true
使用大量if-else分支根据字段类型和规则两个逻辑条件进行判定(最终写了大几百行)
if (type.equal("varchar") || type.equal("text")) {
if(rule.equal("equal")) {
// TODO 判定逻辑
} else if (rule.equal("empty")) {
// TODO 判定逻辑
}
...
} else if (type.equal("integer")) {
if(rule.equal("equal")) {
// TODO 判定逻辑
} else if (rule.equal("empty")) {
// TODO 判定逻辑
}
...
}
...
优点:长驱直入,通俗易懂
缺点:分支判断全在客户端,维护不易,不易扩展,看着恶心
使用策略模式+简单工厂
public interface RuleMatching {
/**
* 规则匹配
* @return
*/
boolean ruleMatching(String indicatorValue, String value1, String value2);
}
public class StringEqual implements RuleMatching {
@Override
public boolean ruleMatching(String indicatorValue, String value1, String value2) {
if (!indicatorValue.equals(value1)) {
return false;
}
return true;
}
}
public class StringInclude implements RuleMatching {
@Override
public boolean ruleMatching(String indicatorValue, String value1, String value2) {
if (!indicatorValue.contains(value1)) {
return false;
}
return true;
}
}
每种类型每种规则都会有一个对应的类
public class RuleMatchingContext {
RuleMatching ruleMatching;
public void init (String operator, String dataType) {
boolean isString = "varchar".equals(dataType);
boolean isIntegerNumber = "integer".equals(dataType);
boolean isBigintNumber = "bigint".equals(dataType);
boolean isDoubleNumber = "double".equals(dataType);
boolean isTime = "timestamp".equals(dataType);
if (isString) {
switch (operator) {
case "equal":
ruleMatching = new StringEqual();
break;
case "unequal":
ruleMatching = new StringUnequal();
break;
...
default:
break;
}
} else if (isIntegerNumber) {
switch (operator) {
case "equal":
ruleMatching = new IntegerEqual();
break;
...
default:
break;
}
} else if (isBigintNumber) {
...
} else if (isDoubleNumber) {
...
} else if (isTime) {
...
}
}
public boolean ruleMatching(String indicatorValue, String value1, String value2) {
return ruleMatching.ruleMatching(indicatorValue, value1, value2);
}
}
RuleMatchingContext ruleMatchingContext = new RuleMatchingContext();
// 根据不同的数据类型和规则由上下文实例化相应的类
ruleMatchingContext.init(conditionRule, indicatorType);
boolean b = ruleMatchingContext.ruleMatching(indicatorValue, value1, value2);
优点:解放了客户端,有新的需求只需要增加相应的类,并在contenxt中添加相应实例化方式。
缺点:类太多了(也不算缺点吧),分支逻辑放在了context中,按设计模式的思想来看,还是没有满足面对修改封闭的原则。
以上便是使用策略模式+简单工厂优化大量if-else分支的具体实现,至于简单工厂的一些弊端,在以后的工厂方法模式和抽象工厂模式中会有更深层的一些探讨,这里暂不啰嗦。