设计模式之策略模式_入门

news2024/9/20 13:17:43

前言

        最近接触了优惠券相关的业务,如果是以前,我第一时间想到的就是if_else开始套,这样的话耦合度太高了,如果后期添加或者删除优惠券,必须直接修改业务代码,不符合开闭原则,这时候就可以选择我们的策略模式(Strategy Pattern)实现解耦,很好的解决上述问题,消除 if-else、switch 多重判断 可以有效应对代码的复杂性,十分优雅!

概念引入

         和上期的建造者模式类似,策略模式也有三个重要元素:

  1. 环境类:用于与策略接口交互的类。
  2. 策略接口:定义所有支持的算法的公共接口。
  3. 具体策略类:实现策略接口的具体算法。

具体案例(针对优惠券的案例)

        我们都知道不同优惠券有不同的优惠力度,非常契合策略模式本案例将结合策略模式和Spring特性来展示: 

        1.创建优惠券的策略接口 

/*
* 优惠券就是一个很好的策略模式的案例
* */
public interface DiscountStrategy {
    //优惠券折扣就可以抽象到接口中
    Double discount(Double price);
    //用于标识不同的折扣力度
    String mark();
}

        我们通过接口来管理优惠券,内部有负责折扣的抽象方法,具体折扣计算由实现类各自负责;还有负责标识的 mark方法。

        2.优惠券的具体实现类

/*
 * 八折的折扣类,首先要实现之前的折扣接口,然后重写方法
 * 利用Spring的特性,将折扣实现类注入IOC容器
 * */

@Component
public class Discount8Strategy implements DiscountStrategy{
    //8折折扣方法
    @Override
    public Double discount(Double price) {
        return price*0.8;
    }

    @Override
    public String mark() {
        return "1";
    }
}

/*
 * 九折的折扣类,首先要实现之前的折扣接口,然后重写方法
 * 利用Spring的特性,将折扣实现类注入IOC容器
 * */

@Component
public class Discount9Strategy implements DiscountStrategy{
    //9折折扣方法
    @Override
    public Double discount(Double price) {
        return price*0.9;
    }

    @Override
    public String mark() {
        return "2";
    }
}

         这里我添加了两种折扣类,分别是8折和9折,同时利用了@Component将二者注入到Spring的IOC容器中,后续将配合Spring完成整个策略模式的实现

         3.优惠券工厂+Spring生命周期使用

/*
 * 这里利用Spring的生命周期,实现InitializingBean方法,在bean初始化这一个阶段做一些处理,实现策略模式
 * */
@Component
public class DiscountStrategyFactory implements InitializingBean {
    //获取到ApplicationContext的实例,可以通过这个获取到想要的类实例
    @Autowired
    private ApplicationContext applicationContext;

    //用来真正存储 (折扣力度标识,对应折扣实例)
    public final HashMap<String,DiscountStrategy> discountStrategies = new HashMap<>();

    //根据标识的mark选择对应的折扣实例,后续可以进行折扣
    public DiscountStrategy chooseDiscount(String mark)
    {
        return discountStrategies.get(mark);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //因为到AfterPropertiesSet这个方法的时候,当前Bean的属性已经设置完成,所以我们可以获取到DiscountStrategy接口的实现类
        //利用Map这个数据类型,完成策略模式
        //使用了GetBeansOfType方法直接返回map类型。key是类的名字,value是对应的实例
        Map<String,DiscountStrategy> discountStrategyMap = applicationContext.getBeansOfType(DiscountStrategy.class);

        //利用stream流的方式遍历,扩充discountStrategies
        discountStrategyMap.forEach((key,value)-> discountStrategies.put(value.mark(),value));
    }
}

        这里策略工厂类实现了InitializingBean接口,是利用了Spring生命周期中的AfterPropertiesSet方法,也就是在Bean初始化后这一个阶段。首先注入ApplicationContext实例,然后利用它调用GetBeanOfType得到(类名,对应实例)这一个Map对象,再利用Stream流进行处理得到了一个Key是mark,value是对应折扣实例的一个map,后续我们就可以使用这个map进行策略模式的使用

        4.具体使用

        折扣成功,这样业务中就可以利用类似的方式处理优惠券,是不是比if_else更加优雅,同时,后期遇到增删改的情况,是不是就符合了开闭原则。 

总结 

         入门了策略模式,我们最后看看他的一些优势:

  • 封装性:策略模式通过将算法封装在独立的类中,使得算法的变化不会影响到使用算法的客户端。
  • 可替换性:可以在运行时选择不同的算法来执行,而不需要修改客户端的代码。
  • 可扩展性:新增算法时,只需新增一个具体的策略类即可,符合开闭原则。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1940631.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3.0学习笔记(一)——vue3简介与vite脚手架的使用

1. 为什么学vue3 Vue3现状&#xff1a; vue-next 2020年09月18日&#xff0c;正式发布vue3.0版本。但是由于刚发布周边生态不支持&#xff0c;大多数开发者处于观望。现在主流组件库都已经发布了支持vue3.0的版本&#xff0c;其他生态也在不断地完善中&#xff0c;这是趋势。…

Python | Leetcode Python题解之第268题丢失的数字

题目&#xff1a; 题解&#xff1a; class Solution:def missingNumber(self, nums: List[int]) -> int:n len(nums)total n * (n 1) // 2arrSum sum(nums)return total - arrSum

Qt第十三章 目录和文件操作

目录和文件操作 文章目录 目录和文件操作设备I/O简介I/O设备的类型基本文件读写QFileQTemporaryFile 流操作QTextStreamQDataStream QFileInfoQDirQFileSystemWatcherQStandardPathsQSettings 设备I/O 简介 I/O设备的类型 基本文件读写 QFile QFile file("C:/Users/PV…

Cisco 路由重发布 —— 实现路由信息在不同路由域间的传递

一、技术背景 在实际的组网中&#xff0c;可能会遇到这样一个场景&#xff1a;在一个网络中同时存在两种或者两种以上的路由协议。例如客户的网络原先是纯 Cisco 的设备&#xff0c;使用 EIGRP 协议将网络的路由打通。但是后来网络扩容&#xff0c;增加了一批华为的设备&#…

HAL库源码移植与使用之低功耗模式

低功耗特性对用电池供电的产品&#xff1a; 更小电池体积&#xff08;降低了大小和成本&#xff09; 延长电池寿命 电磁干扰更小&#xff0c;提高无线通信质量 电源设计更简单&#xff0c;无需过多考虑散热问题 电源供电区分为&#xff1a; 分为VDD供电区…

平面五杆机构运动学仿真matlab simulink

1、内容简介 略 89-可以交流、咨询、答疑 2、内容说明 略 ] 以 MATLAB 程序设计语言为平台 , 以平面可调五杆机构为主要研究对象 , 给定机构的尺寸参数 , 列出所 要分析机构的闭环矢量方程 , 使用 MATLAB 软件中 SIMULINK 仿真工具 , 在 SIMULINK 模型窗口下建立数…

深入理解TensorFlow底层架构

目录 深入理解TensorFlow底层架构 一、概述 二、TensorFlow核心概念 计算图 张量 三、TensorFlow架构组件 前端 后端 四、分布式计算 集群管理 并行计算 五、性能优化 内存管理 XLA编译 六、总结与展望 深入理解TensorFlow底层架构 一、概述 TensorFlow是一个开…

从0开始的STM32HAL库学习8

PWM控制舵机 配置环境 1. 选择TIM2时钟 2.选择内部时钟模式&#xff0c;打开通道二 3.分频系数PSC:72-1 自动重装寄存器ARR:20000-1 输出比较寄存器 CCR:500~2500( 后面可调整 ) 脉冲选择500后期可以改 编辑代码 调用启动函数 HAL_TIM_PWM_Start(&htim2,TIM_CHANN…

一分钟图情论文:《智慧数据视角下古籍数字出版的创新路径》

由武汉大学的雷珏莹和王晓光合著的《智慧数据视角下古籍数字出版的创新路径研究》论文从智慧数据1的视角出发&#xff0c;探讨了我国古籍数字出版的现状及其发展瓶颈&#xff0c;提出了古籍数字出版在内容、形式、服务和技术四个方面的创新路径。 文中, 研究者首先详细分析了当…

使用Fiddler进行Android和IOS抓包

Android抓包 要使用Telerik Fiddler Classic捕获Android设备的网络流量&#xff0c;您需要执行以下步骤&#xff1a; 在Fiddler Classic上进行设置&#xff1a; 确保已安装并使用BouncyCastle作为证书生成器。较新的Android版本会拒绝有效期超过两年的证书&#xff0c;目前只…

构建本地智能知识问答系统:基于Langchain和ChatGLM的简单实践

在数字化时代&#xff0c;智能知识问答系统成为了提升企业效率和数据安全性的关键工具。本文将介绍如何基于Langchain和ChatGLM构建一个本地化、支持中文的智能知识问答系统。该系统不仅能够实现完全本地化推理&#xff0c;而且对开源模型友好&#xff0c;可满足企业对数据隐私…

Windows中修改pip下载源

目录 一. 打开此电脑或文件管理器&#xff0c;输入 %APPDATA% 回车跳转 二. 在此目录中新建一个文件夹命令为pip 三. 进入这个目录&#xff0c;新建一个pip.ini文件 四. 复制阿里云镜像配置 五. CMD终端下载验证 六. 常用的国内镜像网站 一. 打开此电脑或文件管理器…

编程中的智慧六:单例、原型、建造者

上一篇咱们结合Spring介绍了设计模式中的工厂模式相关方法&#xff0c;其实现在Java开发基本上都是基于Spring框架开发&#xff0c;所以后续我们在开发过程中基本上很少自己重写一个工厂模式&#xff0c;都是直接使用Spring来完成。今天咱们接着看剩下的创建型设计模式&#xf…

配置VS+VLC并播放视频

文章目录 前言配置VSVLCVLC播放视频基本流程1. libvlc_new2. libvlc_set_user_agent3. libvlc_set_log_verbosity4. libvlc_media_new_path5. libvlc_media_player_new_from_media6. libvlc_media_player_play7. libvlc_media_player_get_state8. libvlc_media_release9. libvl…

使用9种方法隐藏和显示元素

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>使用9种方法隐藏和显示元素</title><sty…

Bash 学习摘录

文章目录 1、变量和参数的介绍&#xff08;1&#xff09;变量替换$(...) &#xff08;2&#xff09;特殊的变量类型export位置参数shift 2、引用&#xff08;1&#xff09;引用变量&#xff08;2&#xff09;转义 3、条件判断&#xff08;1&#xff09;条件测试结构&#xff08…

数据结构——栈(顺序结构)

一、栈的定义 栈是一种数据结构&#xff0c;它是一种只能在一端进行插入和删除操作的特殊线性表。这一端被称为栈顶&#xff0c;另一端被称为栈底。栈按照后进先出&#xff08;LIFO&#xff09;的原则进行操作&#xff08;类似与手枪装弹后射出子弹的顺序&#xff09;。在计算…

docker 打包orbbec

docker pull humble容器 sudo docker run -it osrf/ros:humble-desktop docker 启动容器 sudo docker run -u root --device/dev/bus/usb:/dev/bus/usb -it -v /home/wl:/share --name wl4 osrf/ros:humble-desktop /bin/bash新开一个终端 查看本地存在的容器&#xff1a;…

【Git】(基础篇六)—— 发现好项目

发现github上的好项目 在开源社区中&#xff0c;发现好的项目&#xff0c;不论是对于自己的学习&#xff0c;还是在前人的基础上继续改进&#xff0c;都十分重要&#xff0c;本文为你介绍如何在github上面找到好的项目&#xff08;gitee同理&#xff09; 关注活跃大牛 GitHu…

Spring的IoC与DI介绍

Spring基础 Spring Framework系统架构 Spring Framework是Spring生态圈中最基础的项目,是其它项目的根基。 IoC(Inversion ofControl)控制反转 使用对象时,由主动new产生对象转换为由外部提供给对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。Sprin…