• 初识设计模式-策略模式-去掉别扭的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。这样的话,代码看起来就会很别扭。所以,在此情况下,我们可以使用策略模式来加以修改代码,优化代码

  • 相关阅读:
    龙兵多企业入驻智能名片小程序源码,多商家电子名片小程序全开源
    【猿创征文】Vue3 企业级优雅实战 - 组件库框架 - 6 搭建example环境
    数据结构与算法:概述
    设备描述符
    数据库连接池种类、C3P0数据库连接池、德鲁伊数据库连接池
    win10/win11安装docker desktop
    如何监控文件已成功通过EDI系统发给客户(三)-997回写
    Electron的学习
    一文搞懂百度强推的Redis天花板笔记,原来数据库是这样理解的
    全网最牛最全的测试开发技术之Docker容器实战
  • 原文地址:https://blog.csdn.net/qq_42582773/article/details/127087620