十三、行为型(策略模式)
策略模式(Strategy Pattern)
概念
策略模式(Strategy Pattern)是一种行为型设计模式,允许定义一系列算法,将每个算法封装在策略类中,并使它们可以互换使用。客户端可以根据需要动态选择不同的策略对象,从而在运行时决定采用哪种具体算法。
应用场景
-
算法的可替换性:当系统有多个不同的算法且这些算法可以互相替换时,可以使用策略模式。例如,排序算法、压缩算法等不同算法的实现。
-
避免条件分支:当系统中存在大量的
if-else或switch-case语句以选择不同的算法或行为时,可以使用策略模式将这些条件分支移入不同的策略类中,减少代码复杂度。 -
动态地选择行为:策略模式允许在运行时动态地选择或切换不同的算法或行为。例如,支付系统中可以选择不同的支付方式(如信用卡、支付宝、微信等)作为策略。
-
解耦行为与使用者:策略模式使得具体的算法实现与使用算法的类解耦,使用者无需了解具体的算法实现,只需使用策略接口即可。
注意点
- 策略的数量:随着算法或行为的增加,策略类的数量也会增加,可能会造成类数量的膨胀。
- 策略的独立性:策略类应当是独立的,相互之间不应依赖。如果策略之间有逻辑关系,可能需要进一步重构。
- 客户端必须知晓策略:客户端需要了解并决定使用哪种策略,可能增加其复杂度。
核心要素
- Strategy(策略接口):定义一系列可供选择的算法或行为。
- ConcreteStrategy(具体策略):具体的算法实现类,每个策略类实现不同的算法。
- Context(上下文类):维护一个策略对象,并根据客户端的选择动态使用不同的策略。
Java代码完整示例
代码示例:简单策略模式
// 定义策略接口
interface Strategy {void execute();
}// 具体策略类 A
class ConcreteStrategyA implements Strategy {@Overridepublic void execute() {System.out.println("使用策略A进行操作");}
}// 具体策略类 B
class ConcreteStrategyB implements Strategy {@Overridepublic void execute() {System.out.println("使用策略B进行操作");}
}// 上下文类,维护一个策略对象
class Context {private Strategy strategy;// 构造函数注入策略对象public Context(Strategy strategy) {this.strategy = strategy;}// 动态设置策略public void setStrategy(Strategy strategy) {this.strategy = strategy;}// 执行策略public void executeStrategy() {strategy.execute();}
}// 客户端代码
public class StrategyPatternDemo {public static void main(String[] args) {// 使用策略AContext context = new Context(new ConcreteStrategyA());context.executeStrategy();// 切换到策略Bcontext.setStrategy(new ConcreteStrategyB());context.executeStrategy();}
}
输出结果:
使用策略A进行操作
使用策略B进行操作
各种变形用法完整示例
-
策略模式结合枚举
通过枚举来实现策略模式,每个枚举实例代表一种策略。代码示例:
enum PaymentStrategy {CREDIT_CARD {@Overridepublic void pay(double amount) {System.out.println("使用信用卡支付: " + amount + " 元");}},PAYPAL {@Overridepublic void pay(double amount) {System.out.println("使用PayPal支付: " + amount + " 元");}},ALIPAY {@Overridepublic void pay(double amount) {System.out.println("使用支付宝支付: " + amount + " 元");}};public abstract void pay(double amount); }public class PaymentContext {private PaymentStrategy strategy;public PaymentContext(PaymentStrategy strategy) {this.strategy = strategy;}public void setStrategy(PaymentStrategy strategy) {this.strategy = strategy;}public void pay(double amount) {strategy.pay(amount);}public static void main(String[] args) {PaymentContext context = new PaymentContext(PaymentStrategy.CREDIT_CARD);context.pay(100.0);context.setStrategy(PaymentStrategy.PAYPAL);context.pay(200.0);context.setStrategy(PaymentStrategy.ALIPAY);context.pay(300.0);} }输出结果:
使用信用卡支付: 100.0 元 使用PayPal支付: 200.0 元 使用支付宝支付: 300.0 元 -
策略模式结合Lambda表达式
在Java 8中,可以使用Lambda表达式简化策略模式的实现,将策略作为函数式接口来处理。代码示例:
interface Strategy {void execute(); }public class StrategyLambdaDemo {public static void main(String[] args) {// 使用Lambda表达式定义不同策略Strategy strategyA = () -> System.out.println("使用策略A执行操作");Strategy strategyB = () -> System.out.println("使用策略B执行操作");// 创建上下文并设置策略Context context = new Context(strategyA);context.executeStrategy();context.setStrategy(strategyB);context.executeStrategy();} }输出结果:
使用策略A执行操作 使用策略B执行操作 -
策略模式结合工厂模式
可以通过工厂模式来创建不同的策略对象,并根据条件动态选择合适的策略。代码示例:
// 定义策略接口 interface Strategy {void execute(); }// 具体策略类 A class ConcreteStrategyA implements Strategy {@Overridepublic void execute() {System.out.println("使用策略A进行操作");} }// 具体策略类 B class ConcreteStrategyB implements Strategy {@Overridepublic void execute() {System.out.println("使用策略B进行操作");} }// 策略工厂类 class StrategyFactory {public static Strategy getStrategy(String type) {switch (type) {case "A":return new ConcreteStrategyA();case "B":return new ConcreteStrategyB();default:throw new IllegalArgumentException("未知策略类型");}} }// 上下文类 class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public void executeStrategy() {strategy.execute();} }// 客户端 public class StrategyFactoryDemo {public static void main(String[] args) {// 通过工厂创建策略对象Context context = new Context(StrategyFactory.getStrategy("A"));context.executeStrategy();context = new Context(StrategyFactory.getStrategy("B"));context.executeStrategy();} }输出结果:
使用策略A进行操作 使用策略B进行操作 -
策略模式结合依赖注入
使用依赖注入框架(如Spring)动态选择策略,这样可以将策略的选择交给框架来管理。代码示例(伪代码):
// 定义策略接口 interface Strategy {void execute(); }// 具体策略类 A @Component("strategyA") class ConcreteStrategyA implements Strategy {@Overridepublic void execute() {System.out.println("使用策略A进行操作");} }// 具体策略类 B @Component("strategyB") class ConcreteStrategyB implements Strategy {@Overridepublic void execute() {System.out.println("使用策略B进行操作");} }// 上下文类 @Component class Context {private final Map<String, Strategy> strategies;// 使用Spring自动注入策略Mappublic Context(Map<String, Strategy> strategies) {this.strategies = strategies;}public void executeStrategy(String strategyType) {Strategy strategy = strategies.get(strategyType);if (strategy != null) {strategy.execute();} else {throw new IllegalArgumentException("未知策略类型");}} }// 客户端 @SpringBootApplication public class StrategySpringDemo {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(StrategySpringDemo.class, args);Context strategyContext = context.getBean(Context.class);strategyContext.executeStrategy("strategyA");strategyContext.executeStrategy("strategyB");} }输出结果:
使用策略A进行操作 使用策略B进行操作
通过这些不同的变形,策略模式不仅能应对多种不同的需求场景,还能与现代开发方法(如枚举、Lambda、工厂模式、依赖注入等)灵活结合,进一步提升代码的可维护性和可扩展性。
相关文章:
十三、行为型(策略模式)
策略模式(Strategy Pattern) 概念 策略模式(Strategy Pattern)是一种行为型设计模式,允许定义一系列算法,将每个算法封装在策略类中,并使它们可以互换使用。客户端可以根据需要动态选择不同的策…...
Vue环境安装以及配置
这里写目录标题 前言一、前置要求1.安装Node.js2. 安装VScode 二、创建全局安装目录和缓存日志目录三、配置环境变量四、权限五、npm换源六、vscode插件1. Vue-Offical2. Vue 3 Snippets3. Path Intellisense4. Auto Import5. Auto Close Tag6. Auto Rename Tag7.GitLens总结 前…...
Redis 数据类型hash(哈希)
目录 1 基本特性 2 主要操作命令 2.1 设置和获取字段 2.1.1 HSET key field value 2.1.2 HGET key field 2.1.3 HMSET key field1 value1 [field2 value2 ...] 2.1.4 HMGET key field1 [field2 ...] 2.2 检查字段是否存在 2.2.1 HEXISTS key field 2.3 获取所有字段…...
单一执行和循环执行的例行性工作
单一执行的例行性工作:只执行一次就结束 1.1at命令的工作过程 /etc/at.allow,写在该文件的人可以使用at命令 /etc/at.deny,黑名单 两个文件如果都不存在,只有root能使用 [rootlocalhost ~]# systemctl status atd [rootlocalh…...
单细胞分析 | Cicero+Signac 寻找顺式共可及网络
引言 在本指南[1]中,将介绍如何利用Cicero工具和单细胞ATAC-seq数据来识别共可接近网络。 为了在Seurat(Signac工具使用的格式)和CellDataSet(Cicero工具使用的格式)之间轻松转换数据,将利用GitHub上的Seur…...
人工智能创造出大量新型蛋白质
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
Palo Alto Networks Expedition 未授权SQL注入漏洞复现(CVE-2024-9465)
0x01 产品介绍: Palo Alto Networks Expedition 是一款强大的工具,帮助用户有效地迁移和优化网络安全策略,提升安全管理的效率和效果。它的自动化功能、策略分析和可视化报告使其在网络安全领域中成为一个重要的解决方案。 0x02 漏洞描述&am…...
c 语言 sprintf
在C语言中,sprintf是一个非常常用的函数,它用于将格式化的数据写入字符串中。sprintf函数的原型通常定义在stdio.h头文件中。 sprintf函数的原型如下: int sprintf(char *str, const char *format, …); 参数说明: str…...
stm32单片机个人学习笔记10(TIM编码器接口)
前言 本篇文章属于stm32单片机(以下简称单片机)的学习笔记,来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记,只能做参考,细节方面建议观看视频,肯定受益匪浅。 STM32入门教程-2023版 细…...
如何在Android中存储数据?
在Android中存储数据是开发过程中至关重要的一环,根据数据的类型、大小、访问频率及安全性需求,开发者可以选择多种存储方式。以下是Android中存储数据的几种主要方式,每种方式都有其特定的应用场景和优缺点。 一、SharedPreferences Share…...
13.3寸工业三防平板数字化工厂产线数采手持终端
在数字化工厂的建设浪潮中,高效可靠的数据采集终端至关重要。尤其在水处理、食品加工等特殊工业环境下,设备的耐用性和数据安全性面临严峻挑战。传统的平板电脑难以应对复杂的工业现场,而一款性能卓越、坚固耐用的工业三防平板则成为提升生产…...
ssh连接慢的问题或zookeeper远程连接服务超时
问题原因: 在SSH登录过程中,服务器会通过反向DNS查找客户端的主机名,然后与登录的IP地址进行匹配,以验证登录的合法性。如果客户端的IP没有域名或DNS服务器响应缓慢,这可能导致SSH登录过慢。为了解决这个问题…...
perf工具使用指导
linux perf工具使用指导 perf 是 Linux 内核自带的性能分析工具,主要用于分析系统性能瓶颈和程序的性能问题。通过合理使用 perf 工具,可以有效地分析和优化系统性能。 安装 perf 在大多数 Linux 发行版中,perf 工具通常随内核源代码包一起…...
WordPress 禁用上传媒体图片自动生成缩略图及多尺寸图片教程
一、在 设置-媒体-媒体设置 中几个尺寸大小的设置不勾选或设置为 0,如下图: 二、找到主题文件 function.php 文件,打开后,在 <?php 后面添加如下代码: function.php 文件路径一般为:WordPress网站根目录…...
锥线性规划【分布鲁棒、两阶段鲁棒方向知识点】
1 锥线性对偶理论 本部分看似和分布鲁棒、两阶段鲁棒优化没什么关系,但值得优先学习,原因将在最后揭晓。 二阶锥 二阶锥(second-order cone,又称ice-cream/Lorentz cone)的形式为: 非负象限锥 半正定锥 …...
linux环境下的程序设计与git操作
目录 前言: 进度条小程序: 先介绍几个背景知识 代码实现 Git操作 总结 其他指令 前言: 本文将重点介绍1. linux下的程序设计,并使用linux下的几个函数接口。实现一个简单的小程序 2.本着开源精神,进行git操作。…...
Matlab中HybridFcn参数的用法
在 MATLAB 中,HybridFcn 参数允许你在全局优化(如遗传算法 ga 或粒子群算法 particleswarm)之后使用局部优化算法进一步微调解的精确度。HybridFcn 通过在全局优化找到的解基础上,进一步调用局部优化器,如 fmincon、pa…...
Leetcode 3316. Find Maximum Removals From Source String
Leetcode 3316. Find Maximum Removals From Source String 1. 解题思路2. 代码实现 题目链接:3316. Find Maximum Removals From Source String 1. 解题思路 这一题思路上的话就是一个动态规划的题目,我们仿照lcs,考察每一个位置是否可以…...
jeecg3版本的vue,离线启动
jeecg的vue2版本已经停止维护,所以只能用vue3的版本。3版本中使用的是pnpm(npm的增强版本)下载依赖。使用pnpm安装的node_modules,不能直接复制到离线主机中(因为在 pnpm安装过程中,会给依赖的配置文件写死…...
C++的内存管理
[TOC} C的内存管理 各个区储存内容 1.栈 局部变量和在执行函数时,函数中创建的局部变量都会在栈上创建,函数执行结束时会被自动释放。从高地址向低地址储存。 2.堆 是new/malloc/calloc/realloc分配的代码块,需要手动释放。如果程序员没…...
C++ 服务端进阶(四)—— 多 Reactor + 协程:真正的高并发模型(融合版)
一、这一篇到底在做什么?到目前为止,你已经分别完成了:✔ 第一篇:Connection(结构抽象)✔ 第二篇:多 Reactor(并发模型)✔ 第三篇:单 Reactor 协程ÿ…...
ViGEmBus:终极Windows虚拟手柄驱动完整使用教程
ViGEmBus:终极Windows虚拟手柄驱动完整使用教程 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus ViGEmBus是一款革命性的Windows内核级虚拟手柄驱…...
Swin2SR在AR/VR中的应用:3D素材高清化处理
Swin2SR在AR/VR中的应用:3D素材高清化处理 1. 引言 在增强现实和虚拟现实的世界里,视觉体验就是一切。当你戴上AR眼镜或VR头盔,看到的每一个细节都直接影响着沉浸感的真实性。但现实往往很骨感——很多3D素材因为历史原因或技术限制&#x…...
TensorRT-LLM与Triton Server部署实战:从环境配置到模型推理
1. 环境准备:从零搭建TensorRT-LLM与Triton Server基础环境 第一次接触TensorRT-LLM和Triton Server时,我花了整整三天时间在环境配置上踩坑。现在回想起来,大部分问题都源于对NVIDIA生态工具链的不熟悉。下面我会用最直白的语言,…...
3大核心策略!Langchain-Chatchat RAG语义匹配效率提升实战指南
3大核心策略!Langchain-Chatchat RAG语义匹配效率提升实战指南 【免费下载链接】Langchain-Chatchat Langchain-Chatchat(原Langchain-ChatGLM)基于 Langchain 与 ChatGLM, Qwen 与 Llama 等语言模型的 RAG 与 Agent 应用 | Langchain-Chatch…...
ICLR2025杰出论文启示录:大模型安全、微调与知识编辑的三大前沿突破
1. 深度安全对齐:从表层防御到系统级防护 大语言模型的安全性问题一直是业界关注的焦点。普林斯顿大学和Google DeepMind的研究团队发现,当前主流的安全对齐方法存在一个致命缺陷——它们只停留在模型输出的前几个token层面。这就好比给房子装防盗门却忘…...
MATLAB三维绘图实战:用plot3和fplot3函数搞定螺旋线与墨西哥帽(附完整代码)
MATLAB三维绘图实战:螺旋线与墨西哥帽的视觉盛宴 在工程计算与科学可视化领域,MATLAB始终保持着不可替代的地位。当二维平面无法完整表达数据的内在规律时,三维图形便成为洞察复杂关系的利器。本文将带您深入探索MATLAB中两大三维曲线绘制神器…...
Jasny Bootstrap按钮标签组件详解:如何优雅地添加图标标签
Jasny Bootstrap按钮标签组件详解:如何优雅地添加图标标签 【免费下载链接】bootstrap The missing components for your favorite front-end framework. 项目地址: https://gitcode.com/gh_mirrors/boots/bootstrap Jasny Bootstrap作为Bootstrap的扩展组件…...
OpenClaw权限管理:千问3.5-9B敏感操作二次确认
OpenClaw权限管理:千问3.5-9B敏感操作二次确认 1. 为什么需要权限管理 上周我差点经历一场"数字灾难"。当时我正在调试OpenClaw自动整理桌面文件的流程,由于模型误解了"清理"指令,它开始删除我最近三个月的工作文档。幸…...
如何通过 proc-macro-workshop 快速掌握 Rust 代码生成技术:终极完整指南
如何通过 proc-macro-workshop 快速掌握 Rust 代码生成技术:终极完整指南 【免费下载链接】proc-macro-workshop Learn to write Rust procedural macros [Rust Latam conference, Montevideo Uruguay, March 2019] 项目地址: https://gitcode.com/gh_mirrors/…...
