初识设计模式-策略模式-去掉别扭的if,满足开闭原则

7大原则

  • 单一职责原则:一个类负责一项职责
  • 里氏替换原则:继承与派生的规则
  • 依赖倒置原则:高层模块不应该依赖底层模块,二者都应该依赖其抽象;抽象不应该依赖其细节;细节应该依赖抽象。即针对接口编程,不要针对实现编程
  • 接口隔离原则:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少
  • 迪米特法则:低耦合,高内聚
  • 开闭原则:一个软件实体和类、模块和函数应该对扩展开放,对修改关闭。
  • 组合/聚合复用原则:尽量使用组合和聚合少使用继承的关系来达到复用的原则。

策略模式原型举例

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

  • TaxStrategy: 税策略接口
  • IntegerTaxStrategy: 价内税策略,负责计算价内税
  • OuterTaxStrategy: 价外税策略,负责计算价外税
  • TaxType: 谁类型定义,当前只有价内税和价外税
  • TaxStrategyFactory: 税策略工厂,根据税类型获取不同的税策略来算税

代码实现

1. 税策略代码
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
}
2. IF语句实现的税策略工厂
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)。
麦凯布最早提出一种称为“基础路径测试”的软件测试方法,测试程序中的每一线性独立路径,所需的测试用例个数即为程序的圈复杂度。
圈复杂度可以用来衡量一个模块判定结构的复杂程度,其数量上表现为独立路径的条数,也可理解为覆盖所有的可能情况最少使用的测试用例个数。
圈复杂度可应用在程序的子程序、模块、方法或类别。

3.税策略工厂中使用Map代替if
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。这样的话,代码看起来就会很别扭。所以,在此情况下,我们可以使用策略模式来加以修改代码,优化代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值