设计模式 行为型 策略模式(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.rhkb.cn/news/502844.html

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

相关文章

如何使用脚手架工具开始,快速搭建一个 Express 项目的基础架构

前言 将从如何使用脚手架工具开始,快速搭建一个 Express 项目的基础架构。接着,文章将详细讲解 Express 中间件的概念、分类以及如何有效地使用中间件来增强应用的功能和性能。最后,我们将讨论如何制定合理的接口规范,以确保 API …

《Opencv》基础操作详解(5)

接上篇:《Opencv》基础操作详解(4)-CSDN博客 目录 接上篇:《Opencv》基础操作详解(4)-CSDN博客 25、轮廓近似 简介 接口用法 参数说明 返回值 代码示例 结果展示 26、轮廓最小外接圆 简介 接口用…

Java虚拟机面试题:内存管理(上)

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

测试用例颗粒度说明

当我们在编写测试用例时,总是会遇到一个问题:如何确定测试用例的颗粒度?测试用例过于粗糙,可能无法全面覆盖系统的细节;而颗粒度过细,又会导致测试重复、冗余。掌握合适的颗粒度,不仅可以提高测…

【C++】深入解析二维数组初始化与越界问题

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯问题代码背景问题现象 💯初步分析与发现的问题1. 二维数组的初始化问题补充说明 2. 数组越界访问为什么数组越界问题没有直接报错? 💯解…

Unity性能优化总结

目录 前言 移动端常见性能优化指标​编辑 包体大小优化 FPS CPU占用率 GPU占用率 内存 发热和耗电量 流量优化 前言 终于有时间了,我将在最近两个项目中进行优化的一些经验进行归纳总结以飨读者。因为我习惯用思维导图,所以归纳的内容主要以图来…

用QT实现 端口扫描工具1

安装在线QT,尽量是完整地自己进行安装,不然会少包 参考【保姆级图文教程】QT下载、安装、入门、配置VS Qt环境-CSDN博客 临时存储空间不够。 Windows系统通常会使用C盘来存储临时文件。 修改临时文件存储位置 打开系统属性: 右键点击“此电…

鸿蒙HarmonyOS开发:基于Swiper组件和自定义指示器实现多图片进度条轮播功能

文章目录 一、概述1、场景介绍2、技术选型 二、实现方案1、图片区域实现2、底部导航点设计3、手动切换 三、所有代码1、设置沉浸式2、外层Tabs效果3、ImageSwiper组件 四、效果展示 一、概述 在短视频平台上,经常可以见到多图片合集。它的特点是:由多张…

【JVM】总结篇-类的加载篇之 类的加载器 和ClassLoader分析

文章目录 类的加载器ClassLoader自定义类加载器双亲委派机制概念源码分析优势劣势如何打破Tomcat 沙箱安全机制JDK9 双亲委派机制变化 类的加载器 获得当前类的ClassLoader clazz.getClassLoader() 获得当前线程上下文的ClassLoader Thread.currentThread().getContextClassLoa…

nginx学习之路-nginx配置https服务器

文章目录 1. 生成证书2. 配置证书1. 拷贝证书文件2. 修改conf/nginx.conf文件内容 3. 查看效果1. 重载配置2. 访问 1. 生成证书 在linux系统下执行,使用openssl命令。(windows环境也可以使用cmder) # 1. 生成私钥 server2025.key(无密码保护…

鸿蒙应用开发搬砖经验之—使用DevTools工具调试前端页面

环境说明: 系统环境:Mac mini M2 14.5 (23F79) 开发IDE:DevEco Studio 5.0.1 Release 配置步骤: 按着官方的指引来慢慢一步一步来,但前提是要配置好SDK的路径(没有配置的话,可能先看下面的配…

【NLP高频面题 - 分布式训练篇】ZeRO主要为了解决什么问题?

【NLP高频面题 - 分布式训练篇】ZeRO主要为了解决什么问题? 重要性:★★ 零冗余优化器技术由 DeepSpeed 代码库提出,主要用于解决数据并行中的模型冗余问题,即每张 GPU 均需要复制一份模型参数。 ZeRO的全称是Zero Redundancy …

《探秘计算机视觉与深度学习:开启智能视觉新时代》

《探秘计算机视觉与深度学习:开启智能视觉新时代》 一、追溯起源:从萌芽到崭露头角二、核心技术:解锁智能视觉的密码(一)卷积神经网络(CNN):图像识别的利器(二&#xff0…

[paddle] 非线性拟合问题的训练

利用paddlepaddle建立神经网络,模拟有限个数据的非线性拟合 本文仍然考虑 f ( x ) sin ⁡ ( x ) x f(x)\frac{\sin(x)}{x} f(x)xsin(x)​ 函数在区间 [-10,10] 上固定数据的拟合。 import paddle import paddle.nn as nn import numpy as np import matplotlib.…

详解GPT-信息抽取任务 (GPT-3 FAMILY LARGE LANGUAGE MODELS)

GPT-3 FAMILY LARGE LANGUAGE MODELS Information Extraction 自然语言处理信息提取任务(NLP-IE):从非结构化文本数据中提取结构化数据,例如提取实体、关系和事件 [164]。将非结构化文本数据转换为结构化数据可以实现高效的数据处…

逆向入门(2)C篇-基础知识

C基础 1、在C中,函数的变量是从右往左传递的,也就是test(x,y),先传入y,再传x。 2、变量的分类: (1)全局变量。在编译的时候就已经确定了内存地址和宽度,变量名就是内存地址的别名…

服务器数据恢复—离线盘数超过热备盘数导致raidz阵列崩溃的数据恢复

服务器数据恢复环境&故障: 一台配有32块硬盘的服务器在运行过程中突然崩溃不可用。经过初步检测,基本上确定服务器硬件不存在物理故障。管理员重启服务器后问题依旧。需要恢复该服务器中的数据。 服务器数据恢复环境: 1、将服务器中硬盘…

Echart实现3D饼图示例

在可视化项目中,很多地方会遇见图表;echart是最常见的;这个示例就是用Echart, echart-gl实现3D饼图效果,复制即可用 //需要安装,再引用依赖import * as echarts from "echarts"; import echar…

PostgreSQL学习笔记(一):PostgreSQL介绍和安装

目录 概念 PostgreSQL简介 PostgreSQL的关键特性 1. 标准兼容性 2. 扩展性 3. 数据完整性和可靠性 4. 丰富的数据类型 5. 查询能力 6. 事务和并发控制 7. 扩展和插件 8. 跨平台和多语言支持 9. 高可用性和扩展性 常用场景 安装 Linux apt安装 下载安装包安装 客…

Linux之信号量

目录 信号量 信号量相关接口 创建信号量 初始化信号量 等待信号量,P操作 发布信号量,V操作 销毁信号量 基于信号量的环形队列下的生产者和消费者模型 环形队列 代码实现 上期我们学习了线程同步的概念,掌握了基于阻塞队列的生产…