现在要实现一个算税策略,税计算类型有价内税和价外税,将来可能会增加新的税类型,初始设计类结构如下

public interface TaxStrategy {
double calc(long amount);
}
class InterTaxStrategy implements TaxStrategy {
@Override
public double calc(long amount) {
System.out.println("内税计算中");
// 获取税率
final double taxRate = 0.2;
return amount * taxRate;
}
}
class OuterTaxStrategy implements TaxStrategy {
@Override
public double calc(long amount) {
System.out.println("外税计算中");
// 获取税率
final double taxRate = 0.2;
return amount / (1 + taxRate) * taxRate;
}
}
// 税类型定义
enum TaxType {
INTER, OUTER
}
public class TaxStrategyFactory {
public static TaxStrategy getTaxStrategy(TaxType taxType) throws Exception {
// 当增加新的税类型时,需要修改代码,同时会增加圈复杂度
if (taxType == TaxType.INTER) {
return new InterTaxStrategy();
} else if (taxType == TaxType.OUTER) {
return new OuterTaxStrategy();
} else {
throw new Exception("The tax type is not supported");
}
}
}
如果通过if语句来获取不同的税策略,当增加新的税策略时就不得不修改已有代码,当算税方法很多时,就不那么好看,同时也增加了圈复杂度
圈复杂度:也称为条件复杂度,是一种衡量代码复杂度的标准,其符号为V(G)。
麦凯布最早提出一种称为“基础路径测试”的软件测试方法,测试程序中的每一线性独立路径,所需的测试用例个数即为程序的圈复杂度。
圈复杂度可以用来衡量一个模块判定结构的复杂程度,其数量上表现为独立路径的条数,也可理解为覆盖所有的可能情况最少使用的测试用例个数。
圈复杂度可应用在程序的子程序、模块、方法或类别。
public class MapTaxStrategyFactory {
// 存储税策略
static Map<TaxType, TaxStrategy> taxStrategyMap = new HashMap<>(16, 0.75F);
// 注册默认税策略
static {
registerTaxStrategy(TaxType.INTER, new InterTaxStrategy());
registerTaxStrategy(TaxType.OUTER, new OuterTaxStrategy());
}
// 提供税注册策略接口,外部只需要调用此接口接口新增税策略,而无需修改策略工厂内部代码
public static void registerTaxStrategy(TaxType taxType, TaxStrategy taxStrategy) {
taxStrategyMap.put(taxType, taxStrategy);
}
// 通过map获取税策略,当增加新的税策略时无需修改代码,对修改封闭,对扩展开放,遵循开闭原则
public static TaxStrategy getTaxStrategy(TaxType taxType) throws Exception {
// 当增加新的税类型时,需要修改代码,同时增加圈复杂度
if (taxStrategyMap.containsKey(taxType)) {
return taxStrategyMap.get(taxType);
} else {
throw new Exception("The tax type is not supported.");
}
}
}
可以看到,进化后IF语句没有了,减少了圈复杂度,增加新的策略后只需调用策略注册接口就好了,不需要修改获取税策略的代码
比如,有些业务中,我们会将付费和退费放在同一个接口中,而如何区分是付费还是退费,我们会根据一个支付状态来区分。一般情况下,我们会根据if判断,但是如何当这个接口中支付状态越来越多的时候,我们会写很多的if-else if。这样的话,代码看起来就会很别扭。所以,在此情况下,我们可以使用策略模式来加以修改代码,优化代码