技术成神之路:设计模式(六)策略模式
1.介绍
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,封装每一个算法,并使它们可以相互替换。策略模式使得算法的变化独立于使用算法的客户端。
2.主要作用
策略模式的主要作用是将算法或行为的选择从使用者中分离出来,使得可以在运行时选择不同的算法或行为。这种方式使得代码更加灵活、可扩展。
3.解决的问题
策略模式的主要作用是通过定义一系列算法,使得它们可以相互替换,从而达到以下几个目的:
- 算法选择:需要根据不同的条件选择不同的算法时,可以使用策略模式避免复杂的条件语句。
- 代码复用:通过封装不同的策略,减少代码重复,提高可复用性。
- 算法独立:使得算法的变化独立于使用它的客户端,便于扩展和维护
4.模式原理
包含角色:
- 策略接口(Strategy):定义一系列算法的接口,所有具体策略都需要实现这个接口。
- 具体策略(ConcreteStrategy):实现策略接口的具体类,每个具体策略实现不同的算法。
- 上下文(Context):持有一个策略的引用,提供选择和使用策略的功能,通常允许在运行时改变所用策略。
UML类图:
代码示例:
使用策略模式来实现不同的排序算法。
// 策略接口
interface SortStrategy {void sort(int[] array);
}// 具体策略:快速排序
class QuickSort implements SortStrategy {public void sort(int[] array) {// 实现快速排序System.out.println("使用快速排序");}
}// 具体策略:冒泡排序
class BubbleSort implements SortStrategy {public void sort(int[] array) {// 实现冒泡排序System.out.println("使用冒泡排序");}
}// 上下文
class SortContext {private SortStrategy strategy;public void setStrategy(SortStrategy strategy) {this.strategy = strategy;}public void sort(int[] array) {strategy.sort(array);}
}// 使用
public class StrategyPatternExample {public static void main(String[] args) {SortContext context = new SortContext();int[] array = {5, 2, 9, 1};context.setStrategy(new QuickSort());context.sort(array); // 输出:使用快速排序context.setStrategy(new BubbleSort());context.sort(array); // 输出:使用冒泡排序}
}
策略模式结构不算复杂,更容易理解,在项目中使用的也比较多,再举个我在项目中遇到的真实案例吧:
当时做跑步机软件,有个需求是需要显示心率值,而心率的来源有多个,比如:心率手柄,华为运动健康,还有其他App,他们之间还有优先级,华为运动健康第一,其他App第二,心率手柄第三,当三个心率源都有心率上报时,需要根据优先级进行显示心率值,而在获取心率值的时候 就只需在 策略模式所说的上下文 中get
就行了,无需关心内部实现,至于策略动态切换,以及其他相关逻辑都包含在了上下文中。
当然,上述概念和举例只是帮助你快速理解策略模式,以及在实际项目中遇到相应需求能想到它就可以了,真实的需求实现肯定不会像示例中那么简单,记得灵活运用。
5.优缺点
优点
- 灵活性:允许在运行时根据需要切换算法。
- 可扩展性:新的算法可以很方便地加入到系统中,无需修改原有的代码。
- 避免条件语句:策略模式避免了复杂的条件语句,使代码更加清晰。
缺点
- 客户端必须了解不同的策略:客户端需要理解不同策略之间的差异,选择合适的策略。
6.应用场景
- 多种算法选择:当需要根据不同条件选择不同算法时,如排序、支付方式等。
- 需要封装一系列的算法:例如图形绘制中,可以根据不同的图形类型选择不同的绘制策略。
- 需要使用不同策略的对象:例如,系统中有多个对象需要使用不同的策略,但又希望统一管理。
这时候你是不是突然想拿自己项目中的某些功能练手了😎,各位不要随便为了设计而修改现有完善模块代码哈,能跑就行 🤪,开个玩笑,设计模式就是为了方便我们写出更容易维护,更适合自己的代码的,而不是为了设计而设计的。
还有还有 说到这了再提一嘴😁
硬编码和条件判断(if…else 或 switch)
大家在项目中写没写过 通过 if...else
或 switch
来选择不同的执行路径,使用哪种算法,哪种解析方式,哪种网络请求… 这中if...else
或 switch
选择方式我们叫做硬编码,当条件足够多的时候,看着很不美观,维护难度也大,恰恰这种类型的代码,可以使用策略模式代替哦!
7.总结
策略模式通过将算法封装为独立的策略类,提供了一种灵活的方式来选择和使用算法。它提高了代码的可维护性和扩展性,符合面向对象设计的基本原则。在需要动态选择算法和减少条件判断时,策略模式是一种非常有效的解决方案。
相关文章:

技术成神之路:设计模式(六)策略模式
1.介绍 策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,封装每一个算法,并使它们可以相互替换。策略模式使得算法的变化独立于使用算法的客户端。 2.主要作用 策略模式的主要作用是将算法或行为…...
华为OD机考题(HJ90 合法IP)
前言 经过前期的数据结构和算法学习,开始以OD机考题作为练习题,继续加强下熟练程度。 描述 IPV4地址可以用一个32位无符号整数来表示,一般用点分方式来显示,点将IP地址分成4个部分,每个部分为8位,表示成…...

值得关注的数据资产入表
不错的讲解视频,来自:第122期-杜海博士-《数据资源入表及数据资产化》-大数据百家讲坛-厦门大学数据库实验室主办第122期-杜海博士-《数据资源入表及数据资产化》-大数据百家讲坛-厦门大学数据库实验室主办-20240708_哔哩哔哩_bilibili...
Postman API性能测试:解锁高级技巧的宝库
🚀 Postman API性能测试:解锁高级技巧的宝库 在API开发和测试过程中,性能测试是确保API稳定性和可靠性的关键环节。Postman作为API测试的强大工具,提供了多种性能测试功能和高级技巧,帮助开发者深入分析API的性能表现…...

stm32中断详解
stm32中断详解 文章目录 stm32中断详解1.什么是中断?1.STM32中断系统特点2.中断处理流程3.中断配置与使用 2.AFIO寄存器3.NVIC寄存器3.中断分组、抢占优先级和响应优先级1. 中断分组2. 抢占优先级3. 响应优先级4.配置与应用 4.中断服务函数5.配置中断流程1.配置外设…...
【LeetCode】最小栈
目录 一、题目二、解法完整代码 一、题目 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。 void push(int val) 将元素val推入堆栈。 void pop() 删除堆栈顶部的元…...

链接追踪系列-09.spring cloud项目整合elk显示业务日志
准备工作: 参看本系列之前篇:服务器安装elastic search 本机docker启动的kibana-tencent 使用本机安装的logstash。。。 本微服务实现的logstash配置如下: 使用腾讯云redis 启动本机mysql 启动本机docker 启动nacos,微服务依赖它作为…...
老年生活照护实训室:让养老护理更个性化
本文探讨了老年生活照护实训室在实现养老护理个性化方面的重要作用。通过分析其提供的实践环境、专业培训、模拟案例和评估机制,阐述了如何培养护理人员的个性化服务能力,以满足老年人多样化的需求,提高养老护理的质量和满意度。 在老龄化社会…...
c++课后作业
把字符串转换为整数 int main() {char pn[21];cout << "请输入一个由数字组成的字符串: ";cin >> pn;int last 0;int res[10];int j strlen(pn);int idx 2;cout << "请选择(2-二进制,10-十进制…...

SpringBoot+Vue实现简单的文件上传(txt篇)
SpringBootVue实现简单的文件上传 1 环境 SpringBoot 3.2.1,Vue 2,ElementUI 2 页面 3 效果:只能上传txt文件且大小限制为2M,选择文件后自动上传。 4 前端代码 <template><div class"container"><el-…...
LLMs之RAG:GraphRAG(本质是名词Knowledge Graph/Microsoft微软发布)的简介、安装和使用方法、案例应用之详细攻略
LLMs之RAG:GraphRAG(本质是名词Knowledge Graph/Microsoft微软发布)的简介、安装和使用方法、案例应用之详细攻略 导读:2024年7月3日,微软正式开源发布GraphRAG。GraphRAG可以提高大型语言模型在私有数据集上的推理能力。 背景痛点࿱…...
Linux 之前的 Unix 桌面沉浮启示录
It takes more than open source, it takes open standards and consensus 仅仅开源还不足以实现开放,还需开放标准和建立共识 Steven J. Vaughan-Nichols Sat 27 Jan 2024 // 12:33 UTC 现在,由于有了安卓和 ChromeOS,Linux 已成为重要的终端…...
面试问题梳理:项目中防止配置中的密码泄露-Jasypt
背景 想起面试的时候,面试官问我现在大家用Spring框架,数据库、ES之类的密码都是配置在配置文件中的,有很大的安全隐患,你有考虑过怎么解决嘛? 当时我回答是可以在项目启动的过程中的命令行追加的方式,感觉…...
engine.addImportPath()用于向 QML 引擎添加新的模块搜索路径
engine.addImportPath() 是 QQmlApplicationEngine 类中的一个方法,用于向 QML 引擎添加新的模块搜索路径。这在需要加载自定义模块或从非标准位置加载 QML 文件时非常有用。通过使用 addImportPath() 方法,可以让 QML 引擎在额外的路径中查找 QML 模块。…...

ServiceNow UI Jelly模板注入漏洞复现(CVE-2024-4879)
0x01 产品简介 ServiceNow 是一个业务转型平台。通过平台上的各个模块,ServiceNow 可用于从人力资源和员工管理到自动化工作流程或作为知识库等各种用途。 0x02 漏洞概述 由于ServiceNow的Jelly模板输入验证不严格,导致未经身份验证的远程攻击者可通过构造恶意请求利用,在…...

项目部署笔记
1、安全组需开放(如果不开放配置nginx也访问不到) 2、域名解析配置IP(子域名也需配置IP,IP地址可以不同) 3、如果出现图片获其他的文件找不到的情况请仔细检查一下路径是否正确 4、服务器nginx配置SSL证书后启动报错: nginx: […...
PyCharm\VsCode——Python第三方库下载换源
为什么要换源? Python第三方库下载默认镜像源在国外,因为特殊的原因在国内的你我利用这个镜像源往往速度会非常地慢,因此为了提速将这个默认镜像源换成国内的镜像源是非常有必要的。 镜像源的种类有哪些? 国外镜像源——官方 http…...

图片上传裁剪react-cropper
效果图 安装插件 npm i react-cropper 或者 yarn add react-cropper 主要代码 import React, { useRef, useState } from react; import Cropper from react-cropper; import cropperjs/dist/cropper.css; import ./index.less; import { UploadOutlined } from ant-d…...
跨越空间的编码:在PyCharm中高效使用远程解释器
跨越空间的编码:在PyCharm中高效使用远程解释器 PyCharm的强大功能之一是支持远程解释器,这使得开发者能够在远程服务器或虚拟机上运行、调试代码,享受本地开发环境的便利。本文将详细介绍如何在PyCharm中配置和使用远程解释器,包…...
Vue3单文件jsx输出多组件示例遇到的坑
感谢博主减肥吧Evan提供的SFC实现多组件的思路和实现,小卷在大佬的基础上再完善下实现。 我们从tsx的API使用上得到启发,可以在vue的单文件组件(sfc)中使用defineComponent来定义和导出多个独立的小组件。此时sfc中的<templat…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...