• 设计模式——策略模式


    1.策略模式简介

    • 1.1 定义:

      原文:Define a family of algorithms, encapsulate each one, and make them interchangeable.
      翻译:定义一系列算法,将它们一个个封装起来,并且使它们之间可以相互替换。

      策略模式也称为政策模式(Policy),让算法独立于使用它的客户而变化,且算法的变化不会影响到使用算法的客户。

    • 1.2 开闭原则(OCP,Open Closed Principle):

      原文:Software entities like classes,modules and functions should be open for extension but closed for modifications.
      翻译:一个软件实体,如类,,模块,,函数等应该对扩展开放,对修改封闭。

      可以通过创建新的策略类来扩展系统的功能,而不需要修改现有的代码。即对扩展开放,对修改关闭。

    • 1.3 单一职责原则(SRP,Single Responsibility Principle):

      原文: A class should have only one reason to change.
      翻译:类发生更改的原因应该只有一个。

      策略模式将不同的算法逻辑分离到不同的策略类中,每个策略类负责实现一种具体的算法。

    • 1.4 理解、使用场景、优缺点

      • 意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
      • 主要解决: 在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
      • 何时使用: 一个系统有许多许多类,而区分它们的只是他们直接的行为。
      • 如何解决: 将这些算法封装成一个一个的类,任意地替换。
      • 关键代码: 实现同一个接口。
      • 优点: ①算法可以自由切换;②避免使用多重条件判断;③扩展性良好。
      • 缺点: ①策略类会增多;②所有策略类都需要对外暴露。

    2.策略模式的应用实例

    • 2.1 功能需求:
      餐厅在付费的时候,会按照不同的角色类型,给予不同的优惠:
      学生在周末的时候可以享受88折优惠学生且周末88折
      学生在工作日的时候可以享受69折优惠学生且工作日69折
      非学生不享受优惠非学生无优惠

    • 2.2 使用策略模式进行功能实现:
      在这里插入图片描述

      • 2.2.1 定义一个不同类型的枚举

        import lombok.AllArgsConstructor;
        import lombok.Getter;
        
        /**
        * 支付类型枚举
        */
        @Getter
        @AllArgsConstructor
        public enum PayTypeEnum {
        
            /** 学生且周末 */
            STUDENT_WEEKEND(1, "studentWeekendStrategy"),
        
            /** 学生但工作日 */
            STUDENT_WORKDAY(2, "studentWorkdayStrategy"),
        
            /** 非学生 */
            NOT_STUDENT(3, "notStudentStrategy")
            ;
        
            /** 支付类型Code */
            private final Integer payTypeCode;
        
            /** 策略名称 */
            private final String strategyName;
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
      • 2.2.2 编写策略接口,给每一种策略都建立对应的策略类
        ①策略接口,IPayTypeStrategy

        /**
        * 支付策略接口
        */
        public interface IPayTypeStrategy {
        
            /**
             * 执行支付逻辑
             */
            void pay();
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10

        学生且周末88折策略实现,StudentWeekendStrategy

        /**
        * 学生且周末的支付策略
        */
        @Component
        public class StudentWeekendStrategy implements IPayTypeStrategy {
        
            @Override
            public void pay() {
                // TODO
                System.out.println("执行88折优惠");
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12

        学生且工作日69折策略实现,StudentWorkdayStrategy

        /**
        * 学生工作日的支付策略
        */
        @Component
        public class StudentWorkdayStrategy implements IPayTypeStrategy {
        
            @Override
            public void pay() {
                // TODO
                System.out.println("执行69折优惠");
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12

        非学生无优惠策略实现,NotStudentStrategy

        /**
        * 非学生的支付策略
        */
        @Component
        public class NotStudentStrategy implements IPayTypeStrategy {
        
            @Override
            public void pay() {
                // TODO
                System.out.println("没有优惠");
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
      • 2.2.3 编写支付策略上下文对象管理类,PayTypeStrategyContext

        /**
        * @description 管理支付策略上下文对象
        */
        @Component
        public class PayTypeStrategyContext {
        
            @Autowired
            private Map<String, IPayTypeStrategy> payTypeStrategyMap = new HashMap<>();
        
            public IPayTypeStrategy getType(PayTypeEnum payTypeEnum) {
                return payTypeStrategyMap.get(payTypeEnum.getStrategyName());
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
      • 2.2.4 功能测试
        ①策略模式业务层接口,IStrategyService

        /**
        * @description 策略模式业务接口
        */
        public interface IStrategyService {
        
            /**
             * 使用策略模式支付
            */ 
            void useStrategy(PayTypeEnum payTypeEnum);
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10

        ②策略模式业务层接口实现类,StrategyServiceImpl

        /**
        * 策略模式业务层接口实现类
        */
        @Service
        public class StrategyServiceImpl implements IStrategyService {
        
            @Autowired
            private PayTypeStrategyContext payTypeStrategyContext;
        
            @Override
            public void useStrategy(PayTypeEnum payTypeEnum) {
                IPayTypeStrategy strategy = payTypeStrategyContext.getType(payTypeEnum);
                strategy.pay();
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15

        ③编写策略模式测试接口,StrategyController

        /**
        * 策略模式测试接口
        */
        @RestController
        @RequestMapping("/test")
        public class StrategyController {
        
            @Autowired
            private IStrategyService strategyService;
        
            // http://localhost:8080/test/pay?payTypeEnum=STUDENT_WEEKEND
            @GetMapping("/pay")
            public void pay(@RequestParam PayTypeEnum payTypeEnum) {
                strategyService.useStrategy(payTypeEnum);
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
  • 相关阅读:
    Java运算符总结一览
    使用Java连接Hadoop进行编程
    LeetCode[145]二叉树的后序遍历
    什么时候不要采用微服务架构
    MySQL进阶02_索引概述_结构_分类_语法
    第一次复习SpringBoot知识点记录
    git安装 免密交互 clone push
    Redis 典型应用——缓存(缓存预热,穿透,雪崩,击穿)
    MinDoc文档管理系统在宝塔环境安装教程
    音视频SDP协议详解(描述会话的协议)
  • 原文地址:https://blog.csdn.net/weixin_42541479/article/details/136472983