1.策略模式定义

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一组算法,将每个算法封装起来,并使它们可以相互替换,从而让算法的变化独立于使用它的客户(Client)。

换句话说, 策略模式让一个类的行为或其算法可以在运行时更改,而不会影响使用该类的代码。

UML图:

在这里插入图片描述

2.策略模式举例:

业务场景:需要实现一个商场收银系统,有三种策略,

  1. 正常结账
  2. 打折
  3. 满减
    实现业务功能如下:

2.1 代码设计UML图如下:

在这里插入图片描述

2.2 关键代码:

CashContext代码:和抽象工厂结合,减少耦合。之前客户端需要了解CashContext和CashSuper两个类,现在只需要了解CashContext一个类,封装更好,耦合更小。

public class CashContext {private CashSuper cs;   //声明一个CashSuper对象//通过构造方法,传入具体的收费策略public CashContext(int cashType){switch(cashType){case 1:this.cs = new CashNormal();break;case 2:this.cs = new CashRebate(0.8d);break;case 3:this.cs = new CashRebate(0.7d);break;case 4:this.cs = new CashReturn(300d,100d);break;}}public double getResult(double price,int num){//根据收费策略的不同,获得计算结果return this.cs.acceptCash(price,num);}    
}

CashSuper:


public abstract class CashSuper {public abstract double acceptCash(double price,int num);
}

CashReturn:

public class CashReturn extends CashSuper {private double moneyCondition = 0d; //返利条件private double moneyReturn = 0d;    //返利值//返利收费。初始化时需要输入返利条件和返利值。//比如“满300返100”,就是moneyCondition=300,moneyReturn=100public CashReturn(double moneyCondition,double moneyReturn){this.moneyCondition = moneyCondition;this.moneyReturn = moneyReturn;}//计算收费时,当达到返利条件,就原价减去返利值public double acceptCash(double price,int num){double result = price * num;if (moneyCondition>0 && result >= moneyCondition)result = result - Math.floor(result / moneyCondition) * moneyReturn; return result;}}

客户端代码:

public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("策略模式和简单工厂模式");System.out.println();		int discount = 0; 		//商品折扣模式(1.正常收费 2.打八折 3.打七折)double price = 0d; 		//商品单价int num = 0;			//商品购买数量double totalPrices = 0d;//当前商品合计费用double total = 0d;		//总计所有商品费用Scanner sc = new Scanner(System.in);do {System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");	discount = Integer.parseInt(sc.nextLine());System.out.println("请输入商品单价:");	price = Double.parseDouble(sc.nextLine());System.out.println("请输入商品数量:");	num = Integer.parseInt(sc.nextLine());System.out.println();	if (price>0 && num>0){//根据用户输入,将对应的策略对象作为参数传入CashContext对象中CashContext cc = new CashContext(discount);//通过Context的getResult方法的调用,可以得到收取费用的结果//让具体算法与客户进行了隔离totalPrices = cc.getResult(price,num);total = total + totalPrices;System.out.println();	System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	System.out.println();System.out.println("总计:"+ total+"元");	System.out.println();}}while(price>0 && num>0);System.out.println();System.out.println("**********************************************");}
}

具体运行结果如下:
在这里插入图片描述

3.策略模式优缺点

✅ 优点

  • 符合开闭原则(Open-Closed Principle):可以新增新的策略,而不影响已有代码。
  • 避免冗长的 if-else 语句:如果不使用策略模式,可能会有大量 if-else 逻辑判断。
  • 支持动态切换:可以在运行时自由更换不同的算法,而不修改原有代码。
  • 代码更符合SOLID原则
设计原则策略模式如何符合
单一职责原则(SRP)每个 Strategy 只负责一个算法,职责清晰。
开闭原则(OCP)可以新增策略,而不修改原代码。
依赖倒置原则(DIP)Context 依赖于 Strategy 接口,而不是具体实现。

❌ 缺点

  • 增加了代码复杂度:每个策略都需要定义一个类,当策略过多时,会导致类爆炸。
  • 客户端需要了解不同策略:调用方需要知道有哪些可用策略,才能正确选择。

4.策略模式的应用场景

✅ (1) 算法的可替换性

计算税收(不同国家税率)
支付方式(微信支付、支付宝、银行卡)

✅ (2) 处理不同格式的文件

解析 JSON、XML、CSV 文件时,使用不同的解析策略。

✅ (3) AI/机器学习中的优化策略

训练模型时,可以使用不同的优化算法(SGD、Adam、RMSprop)。

5.策略模式 vs 其他模式

设计模式作用适用场景
策略模式允许在运行时更换不同算法当有多种算法可选,且希望避免 if-else 逻辑。
状态模式允许对象在不同状态下表现出不同行为对象的行为依赖于状态变化,例如订单状态。
工厂模式负责创建对象,但不指定其具体实现需要动态创建不同策略对象时,可结合策略模式使用。

6.总结

策略模式核心思想: 定义一组算法,让它们可以互相替换,而不会影响客户端代码。
适用于: 需要多个可替换算法,并希望避免 if-else 逻辑的场景。
优点: 符合开闭原则,可动态切换策略,避免冗长 if-else
缺点: 可能会增加类的数量,使代码更复杂。

7.参考引用

  • https://juejin.cn/post/7485322373614813220

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AWS DMS 深度解析:从迁移任务到复制任务 - 全流程指南与最佳实践

AWS Database Migration Service (DMS) 是一项强大的云服务,用于在源数据库和目标数据库之间安全地迁移数据。其核心优势在于支持几乎零停机时间的迁移,这主要归功于其“变更数据捕获 (CDC)”功能。理解迁移任务 (Migration Task) 和复制任务 (Replication Task) 的关系与操作…

国企社招 | 中国邮政2025年社会招聘开启

添加图片注释,不超过 140 字(可选) 添加图片注释,不超过 140 字(可选) 添加图片注释,不超过 140 字(可选) 原文链接:“邮”你“政”好 | 广东邮政2025年社会…

linux添加自启动

linux添加自启动 配置步骤: 创建systemd服务文件 sudo nano /etc/systemd/system/tme-vod.service将下面artifact中的内容复制到该文件中。 [Unit] DescriptionTME VOD Service Afternetwork.target[Service] Typesimple Userroot Grouproot WorkingDirectory/data/…

轻量级解决方案:如何高效处理Word转PDF?

文档格式转换时,手动逐个处理总显得效率低下。它的体积小巧,不到1MB,且无界面设计,运行极简:将其与Word文件放入同一目录,双击启动,程序便会自动完成所有文档的PDF转换。操作零复杂度&#xff0…

Redis 数据倾斜

Redis 数据倾斜指的是在 Redis 集群模式下,数据(以及相应的访问请求和负载)在各个分片(Shard)之间分布严重不均匀的现象。这会导致部分节点成为热点或超载,而其他节点资源闲置,最终引发性能瓶颈…

Java基础-TCP通信(多发多收和一发一收)

目录 案例要求: 实现思路: 代码: User:客户端 Client:服务端 总结: 案例要求: 实现TCP通信的多发多收和一发一收,多发多收去掉各自的while循环就是一发一收,本文只模拟一发一收 实现思路: 客户端(U…

WinForm 对话框的 Show 与 ShowDialog:阻塞与非阻塞的抉择

目录 核心概念:阻塞与非阻塞 Show 与 ShowDialog 的详细对比 代码示例:两种方式的实现差异 使用 Show () 显示非模态对话框 使用 ShowDialog () 显示模态对话框 适用场景分析 适合使用 Show () 的场景 适合使用 ShowDialog () 的场景 最佳实践与…

晓知识: 动态代理与静态代理的区别

动态代理与静态代理的区别 代理模式是一种常见的设计模式,用于在不修改原始类的情况下扩展其功能。代理分为静态代理和动态代理两种,它们在实现方式、适用场景和灵活性上有显著差异。 静态代理 静态代理在编译时就已经确定代理类和被代理类的关系。代理类…

Linux系统编程Day9 -- gdb (linux)和lldb(macOS)调试工具

往期内容回顾 Git 教程(初阶) 基于Linux系统知识的第一个程序 自动化构建工具-make/Makefile gcc/g编译及链接 Vim工具的使用 Linux常用工具(yum与vim) 一、 Linux 下的调试工具 GDB 一、为什么要学习 GDB? 调试是开发…

数据结构(17)排序(下)

一、计数排序计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。操作步骤如下:①统计相同元素出现的次数 ②根据统计的结果将序列回收到原来的序列中比如,现在有一个数组{6,1,2,9,4,2,4,1,4}。该数组中,元素1出现两次&#…

深度解析 Spring Boot 循环依赖:原理、源码与解决方案

在 Spring Boot 开发中,循环依赖是一个常见且容易被忽视的技术点。当两个或多个 Bean 相互引用时,就会形成循环依赖(如 A 依赖 B,B 依赖 A)。初学者往往会困惑:Spring 为什么能自动处理这种看似矛盾的依赖关系?本文将从原理、源码实现到解决方案,全方位剖析 Spring Boo…

数据库的基本操作(约束与DQL查询)

一、约束约束是在表上强制执行的数据规则,用于确保数据的完整性和一致性(1)约束类型MySQL中支持多种约束类型:①主键约束(PRIMARY KEY) ②自增约束(AUTO_INCREMENT)③非空约束…

HP Pavilion G6 笔记本安装Ubuntu开机后自动进入飞行模式的问题解决

问题一台HP Pavilion G6 笔记本 ,安装了Ubuntu24.04版本,开机后,直接进入飞行模式,导致无法使用Wifi,且使用fnf10的组合键,也无法关闭飞行模式。使用fnf10键,可以看到提示显示飞行模式,但无法关…

LLM:MoE原理与实现探索

文章目录前言一、Deepseek Moe二. Moe架构1. Expert2. Gate3. MoE Module三、Auxiliary Loss总结前言 MoE(Mixture of Experts) 已经逐渐在LLM中广泛应用,其工程部署相关目前也有了越来越多的支持,本文主要记录一下MoE的基本模块构造与原理。…

基于领域事件驱动的微服务架构设计与实践

引言:为什么你的微服务总是"牵一发而动全身"? 在复杂的业务系统中,你是否遇到过这样的困境:修改一个订单服务,却导致支付服务异常;调整库存逻辑,用户服务开始报错。这种"蝴蝶效应…

如何使用curl编程来下载文件

libcurl 是一个功能强大的跨平台网络传输库,支持多种协议。 本篇来介绍libcul的C语言编程,实现一个文件下载的功能。 1 curl基础介绍 1.1 核心数据结构 1.1.1 CURL句柄 CURL是libcurl 的核心句柄,每个请求对应一个 CURL 实例,…

大语言模型提示工程与应用:ChatGPT提示工程技术指南

ChatGPT提示工程 学习目标 在本课程中,我们将学习更多关于ChatGPT的最新提示工程技术。 相关知识点 ChatGPT提示工程 学习内容 1 ChatGPT提示工程 ChatGPT是OpenAI研发的新型对话模型,具备多轮对话能力。该模型通过人类反馈强化学习(RLHF)训练&am…

能力评估:如何系统评估你的技能和经验

能力评估:如何系统评估你的技能和经验 作为一名38岁的互联网研发老兵,你已经积累了丰富的经验,包括技术深度、项目管理、团队协作等。但能力评估不是一次性事件,而是持续过程,帮助你识别优势、短板,并为职业…

鸿蒙开发中所有自定义装饰器的完整案例解析--涵盖 16 个核心装饰器的详细用法和实战场景

以下是鸿蒙开发中 所有自定义装饰器的完整案例解析 和 终极总结指南,涵盖 16 个核心装饰器的详细用法和实战场景: 一、终极总结表:16大装饰器全景图 装饰器类别V1V2核心作用典型场景Component组件定义✅❌创建标准组件业务UI组件ComponentV2…

【C++】哈希表的实现(unordered_map和unordered_set的底层)

文章目录 目录 文章目录 前言 一、unordered_set和unordered_map介绍 二、哈希表的介绍 三、哈希冲突的解决方法 1.开放定址法 2.链地址法 四、两种哈希表代码实现 总结 前言 前面我们学习了红黑树,红黑树就是map和set的底层,本篇文章带来的是unordered…