设计模式 行为型 策略模式(Strategy Pattern)与 常见技术框架应用 解析

在这里插入图片描述
策略模式(Strategy Pattern)核心思想是将算法的实现从使用该算法的类中分离出来,作为独立的对象,通过接口来定义算法家族,这样就可以很容易地改变或扩展算法。通过这种方式,可以避免在客户端代码中使用大量的条件语句来选择不同的行为方式,从而提高了代码的灵活性和可维护性。

一、核心思想

策略模式(Strategy Pattern)是一种行为设计模式,它允许对象在运行时动态地选择算法或行为。其核心思想是“定义一系列算法,将每个算法都封装起来,并且使它们之间可以互换”,从而增加系统的灵活性和可扩展性。

二、定义与结构

  • 定义:策略模式是一种行为设计模式,它定义了一系列算法,将每个算法封装起来,并使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。
  • 结构
    • 环境(Context)类:它是使用策略的类,维护一个对策略对象的引用。在游戏角色的例子中,角色类就是环境类,它会有一个属性来保存攻击策略。
    • 抽象策略(Strategy)类:定义了一个公共接口,用于所有具体策略类实现。比如定义一个attack()接口,所有不同的攻击策略都要实现这个接口。
    • 具体策略(Concrete Strategy)类:实现了抽象策略类中的接口,提供具体的算法实现。例如战士的近身攻击策略类和法师的远程攻击策略类。

三、角色

  • 环境(Context)角色
    • 持有一个具体策略的对象,可以动态地改变持有的策略对象,并在运行时调用具体策略的方法。
  • 抽象策略(Strategy)角色
    • 定义了一个公共接口,所有的具体策略类都必须实现这个接口。
  • 具体策略(Concrete Strategy)角色
    • 实现了抽象策略接口,封装了具体的算法或行为。

四、实现步骤及代码示例

  1. 步骤一:定义抽象策略类
// 抽象策略接口
public interface MemberStrategy {double calcPrice(double booksPrice);
}
  1. 步骤二:定义具体策略类
// 具体策略类:初级会员折扣
public class PrimaryMemberStrategy implements MemberStrategy {@Overridepublic double calcPrice(double booksPrice) {System.out.println("对于初级会员没有折扣");return booksPrice;}
}// 具体策略类:中级会员折扣
public class IntermediateMemberStrategy implements MemberStrategy {@Overridepublic double calcPrice(double booksPrice) {System.out.println("对于中级会员的折扣为10%");return booksPrice * 0.9;}
}// 具体策略类:高级会员折扣
public class AdvancedMemberStrategy implements MemberStrategy {@Overridepublic double calcPrice(double booksPrice) {System.out.println("对于高级会员的折扣为20%");return booksPrice * 0.8;}
}
  1. 步骤三:定义环境类
// 环境类
public class Price {private MemberStrategy strategy;public Price(MemberStrategy strategy) {this.strategy = strategy;}public double quote(double booksPrice) {return this.strategy.calcPrice(booksPrice);}
}
  1. 步骤四:使用策略模式
// 客户端代码
public class Client {public static void main(String[] args) {// 选择并创建需要使用的策略对象MemberStrategy strategy = new AdvancedMemberStrategy();// 创建环境对象Price price = new Price(strategy);// 计算价格double quote = price.quote(300);System.out.println("图书的最终价格为: " + quote);}
}

五、常见技术框架应用

1、排序算法

在Python中,sorted()函数就使用了策略模式的思想。sorted()函数可以接受一个key参数,这个key参数实际上就是一个策略。

# 定义一个简单的列表
my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
# 按照元素大小排序(默认策略)
sorted_list_default = sorted(my_list)
print(sorted_list_default)
# 定义一个按照元素绝对值大小排序的策略
def absolute_value_key(item):return abs(item)
sorted_list_absolute = sorted(my_list, key = absolute_value_key)
print(sorted_list_absolute)

2、支付方式

以下是一个使用策略模式在前端框架中实现不同支付方式的示例代码:

// 定义支付策略接口
interface PaymentStrategy {pay(amount: number): void;
}// 实现具体的支付策略类(如支付宝支付、微信支付等)
class AlipayStrategy implements PaymentStrategy {pay(amount: number) {console.log(`使用支付宝支付了:${amount}`);}
}class WeChatPayStrategy implements PaymentStrategy {pay(amount: number) {console.log(`使用微信支付了:${amount}`);}
}// 定义上下文类,用于持有支付策略的引用并在需要时调用具体的支付策略
class PaymentContext {private paymentStrategy: PaymentStrategy;setPaymentStrategy(strategy: PaymentStrategy) {this.paymentStrategy = strategy;}executePayment(amount: number) {this.paymentStrategy.pay(amount);}
}// 使用示例
const context = new PaymentContext();
context.setPaymentStrategy(new AlipayStrategy());
context.executePayment(100);  // 输出: 使用支付宝支付了:100元context.setPaymentStrategy(new WeChatPayStrategy());
context.executePayment(200);  // 输出: 使用微信支付了:200元

在这个示例中,我们定义了一个支付策略接口PaymentStrategy,并实现了两个具体的支付策略类AlipayStrategyWeChatPayStrategy。然后,我们定义了一个上下文类PaymentContext,它持有一个支付策略的引用,并提供了设置支付策略和执行支付的方法。在客户端代码中,我们可以通过设置不同的支付策略来动态地选择支付方式。

六、应用场景

多个类只在行为上有区别,而算法和行为需要在运行时可互换的场景。
需要避免使用多重条件转移语句的场景。
当需要使用不同的变体算法时。算法族被定义成一系列的算法类,而每类实现一种算法的场景。

策略模式广泛应用于各种需要算法替换和行为切换的场景中,如:

  1. 促销活动:满减促销、返现促销、打折促销等。
  2. 排序算法:快速排序、归并排序、堆排序等。
  3. 数据搜索:二分搜索、线性搜索等。
  4. 支付方式:信用卡支付、第三方支付、货到付款等。
  5. 数据压缩:无损压缩(如zip、gzip)和有损压缩(如jpeg、mp3)。
  6. 游戏AI:根据不同关卡和难度,切换敌人的行为策略或玩家的辅助策略。

七、优缺点

优点

  1. 可扩展性强:可以很容易地添加新的策略,只要实现抽象策略类的接口即可。例如在游戏中添加新的角色攻击方式,只需要创建一个新的具体策略类。
  2. 代码复用性高:具体策略类可以在多个环境类中复用。例如不同的游戏场景可能都用到战士的攻击策略。
  3. 符合开闭原则:对扩展开放,对修改关闭。当需要添加新策略时,不需要修改环境类和其他已有的策略类。

缺点

  1. 策略类数量增多:如果有很多策略,会导致策略类的数量增加,使得代码结构变得复杂,需要管理更多的类。
  2. 客户端必须了解策略差异:客户端(环境类)需要知道不同策略之间的区别,才能正确地选择和使用策略。例如在游戏角色选择攻击策略时,需要知道每个策略对应的攻击方式。

在这里插入图片描述

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

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

相关文章

如何操作github,gitee,gitcode三个git平台建立镜像仓库机制,这样便于维护项目只需要维护一个平台仓库地址的即可-优雅草央千澈

如何操作github,gitee,gitcode三个git平台建立镜像仓库机制,这样便于维护项目只需要维护一个平台仓库地址的即可-优雅草央千澈 问题背景 由于我司最早期19年使用的是gitee,因此大部分仓库都在gitee有几百个库的代码,…

B+树的原理及实现

文章目录 B树的原理及实现一、引言二、B树的特性1、结构特点2、节点类型3、阶数 三、B树的Java实现1、节点实现2、B树操作2.1、搜索2.2、插入2.3、删除2.4、遍历 3、B树的Java实现示例 四、总结 B树的原理及实现 一、引言 B树是一种基于B树的树形数据结构,它在数据…

大纲笔记幕布的替换

文章目录 前言类似的大纲软件探索 DynalistLogseq通过国内代码仓库建立 Git 仓库Logseq 的使用PC 端安卓端Git 操作Termux git 步骤Termux 的桌面组件:Termux widget 报错参考 前言 之前我一直用幕布,买了三年,奈何要过期了,又三…

MoEs and Transformers 笔记

ref:https://huggingface.co/blog/zh/moe#%E7%94%A8router-z-loss%E7%A8%B3%E5%AE%9A%E6%A8%A1%E5%9E%8B%E8%AE%AD%E7%BB%83 MoEs and Transformers Transformer 类模型明确表明,增加参数数量可以提高性能,因此谷歌使用 GShard 尝试将 Transformer 模型…

ubuntu为Docker配置代理

终端代理 我们平常在ubuntu终端中使用curl或git命令时,往往会很慢。 所以,首先需要给ubuntu终端环境添加代理。 查看自身那个软件的端口号,我这里是7890。 sudo gedit ~/.bashrcexport http_proxyhttp://localhost:7890 export https_pr…

【安卓开发】【Android Studio】项目构建失败提示【Could not read metadata.bin】解决方法

一、问题说明 在Android Studio中开发安卓项目时,项目构建失败,提示如下: Could not read workspace data from xxx/xxx/(某个目录,和gradle有关):could not read ...metadata.bin&#xff08…

EXCEL: (二) 常用图表

10. 图表 134-添加.删除图表元素 图表很少是一个单独的整体,而是由十几种元素/对象拼凑出来的。 学习图表就是学习当中各类元素的插删改。 ①图表中主要元素的定义 图表上的一个颜色就是一个系列。 横轴是分类轴,将每个系列都分为几类。 ②选中图…

sys.dm_exec_connections:查询与 SQL Server 实例建立的连接有关的信息以及每个连接的详细信息(客户端ip)

文章目录 引言I 基于dm_exec_connections查询客户端ip权限物理联接时间范围dm_exec_connections表see also: 监视SQL Server 内存使用量资源信号灯 DMV sys.dm_exec_query_resource_semaphores( 确定查询执行内存的等待)引言 查询历史数据库客户端ip应用场景: 安全分析缺乏…

阿里云发现后门webshell,怎么处理,怎么解决?

当收到如下阿里云通知邮件时,大部分管理员都会心里一惊吧!出现Webshell,大概是网站被入侵了。 尊敬的 xxxaliyun.com: 云盾云安全中心检测到您的服务器:47.108.x.xx(xx机)出现了紧急安全事件…

【大模型】百度千帆大模型对接LangChain使用详解

目录 一、前言 二、LangChain架构与核心组件 2.1 LangChain 核心架构 2.2 LangChain 核心组件 三、环境准备 3.1 前置准备 3.1.1 创建应用并获取apikey 3.1.2 开通付费功能 3.2 获取LangChain文档 3.3 安装LangChain依赖包 四、百度千帆大模型对接 LangChain 4.1 LL…

maven如何从外部导包

1.找到你项目的文件位置,将外部要导入的包复制粘贴进你当前要导入的项目下。 2.从你的项目目录下选中要导入的包的pom文件即可导包成功 注意一定是选中对应的pom文件 导入成功之后对应的pom.xml文件就会被点亮

graylog配置日志关键字邮件Email告警

文章目录 前言一、配置邮箱报警二、邮件告警配置1.设置邮箱告警通知2.设置告警事件 三、告警结果示例 前言 在TO/B、TO/C项目的告警链路中,端口告警、服务器基础资源告警、接口告警等不同类型的告警都扮演着重要角色。这些告警能够帮助团队及时发现潜在的系统问题&…

GraphQL:强大的API查询语言

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

集合卡尔曼滤波ENKF的学习笔记

集合卡尔曼滤波ENKF的学习笔记 什么是数据同化?天气模型预测是25C(这叫"背景场"),实际观测是23C(这叫"观测值"),数据同化就是把这两个信息合理结合。 # 最简单的组合方式&…

DeepSeek-V3 通俗详解:从诞生到优势,以及与 GPT-4o 的对比

1. DeepSeek 的前世今生 1.1 什么是 DeepSeek? DeepSeek 是一家专注于人工智能技术研发的公司,致力于打造高性能、低成本的 AI 模型。它的目标是让 AI 技术更加普惠,让更多人能够用上强大的 AI 工具。 1.2 DeepSeek-V3 的诞生 DeepSeek-V…

UI自动化测试保姆级教程--pytest详解(精简易懂)

欢迎来到啊妮莫的学习小屋 别让过去的悲伤,毁掉当下的快乐一《借东西的小人阿莉埃蒂》 简介 pytest是一个用于Python的测试框架, 支持简单的单元测试和复杂的功能测试. 和Python自带的UnitTest框架类似, 但是相比于UnitTest更加简洁, 效率更高. 特点 非常容易上手…

Javascript算法——贪心算法(一)

贪心算法详解(JavaScript)(局部最优->全局最优) 贪心算法(Greedy Algorithm)是一种在每一步选择中都采取当前状态下的最优选择(局部最优)的算法设计方法。通过局部最优解的累积&…

CK18——肝损伤无创诊断标志物

肝脏作为人体至关重要的代谢与解毒器官,极易遭受病毒、药物、酒精及不良饮食等多种因素的损害,进而引发一系列如非酒精性脂肪肝(NAFLD)、肝纤维化、肝硬化、肝细胞癌以及各类肝炎等病症。因此,确定一种高可靠性、非侵入…

.NET Core + Kafka 开发指南

什么是Kafka Apache Kafka是一个分布式流处理平台,由LinkedIn开发并开源,后来成为Apache软件基金会的顶级项目。Kafka主要用于构建实时数据管道和流式应用程序。 Kafka 架构 从下面3张架构图中可以看出Kafka Server 实际扮演的是Broker的角色, 一个Kafka Cluster由多个Bro…

[离线数仓] 总结二、Hive数仓分层开发

接 [离线数仓] 总结一、数据采集 5.8 数仓开发之ODS层 ODS层的设计要点如下: (1)ODS层的表结构设计依托于从业务系统同步过来的数据结构。 (2)ODS层要保存全部历史数据,故其压缩格式应选择压缩比率,较高的,此处选择gzip。 CompressedStorage - Apache Hive - Apac…