当前位置: 首页 > news >正文

【设计模式】Java 设计模式之模板策略模式(Strategy)

策略模式详解:模式结构、实现与应用场景

一、策略模式概述

策略模式是一种行为设计模式,它使得算法可以独立于使用它的客户端变化。策略模式使得算法可以在运行时切换,从而增强了系统的灵活性和可维护性。在策略模式中,我们定义一系列的算法,并将每一个算法封装起来,使它们可以互相替换。策略模式使得算法可以独立于使用它的客户端变化。

二、策略模式结构

策略模式包含三个主要角色:

  1. Context(上下文):它用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。
  2. Strategy(策略):这是一个策略接口,定义了所有支持的算法的公共接口。
  3. ConcreteStrategy(具体策略):实现了Strategy接口,封装了具体的算法或行为。

三、策略模式的实现方式

策略模式的实现通常包括定义一个策略接口和多个实现了该接口的具体策略类。上下文类持有对策略对象的引用,并在运行时根据需要动态地切换策略对象。

示例代码

// 策略接口
public interface PaymentStrategy {void pay(double amount);
}// 具体策略A:信用卡支付
public class CreditCardPayment implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("Paying by credit card: " + amount);// 信用卡支付逻辑}
}// 具体策略B:现金支付
public class CashPayment implements PaymentStrategy {@Overridepublic void pay(double amount) {System.out.println("Paying by cash: " + amount);// 现金支付逻辑}
}// 上下文类
public class PaymentContext {private PaymentStrategy paymentStrategy;public PaymentContext(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void executePayment(double amount) {paymentStrategy.pay(amount);}
}

四、策略模式的优点

  1. 开闭原则:策略模式对扩展开放,对修改封闭。增加新的策略只需要增加新的策略类,无需修改已有代码。
  2. 灵活性:策略模式使得算法可以独立于使用它的客户端变化,客户端可以动态地选择使用哪种策略。
  3. 简化单元测试:策略模式使得每一个算法都有自己的类,这样算法可以独立地进行单元测试。

五、策略模式的缺点

  1. 客户端必须知道策略的存在:客户端需要了解不同策略的存在,并显式地选择使用哪种策略。
  2. 策略类可能过多:当策略数量较多时,会导致策略类数量膨胀,增加系统复杂性。

六、常见的应用场景

  1. 排序算法:不同的排序算法(如冒泡排序、快速排序等)可以作为不同的策略实现。
  2. 日志记录:不同的日志记录级别(如DEBUG、INFO、ERROR)可以使用不同的日志记录策略。
  3. 支付方式:在电商系统中,不同的支付方式(如信用卡支付、现金支付、第三方支付等)可以作为不同的策略实现。

七、应用案例解读

以电商系统的支付功能为例,策略模式可以很好地应用。电商系统需要支持多种支付方式,每种支付方式都有自己的处理逻辑。使用策略模式,我们可以定义一个支付策略接口,并为每种支付方式实现一个具体的策略类。在支付流程中,根据用户选择的支付方式,动态地创建并使用相应的支付策略对象进行支付操作。这样,当需要添加新的支付方式时,只需实现新的策略类并集成到系统中即可,无需修改已有的代码。

八、总结

策略模式是一种强大而灵活的设计模式,它允许我们在运行时动态地改变对象的行为。通过封装算法或行为到独立的策略类中,我们提高了代码的复用性和可维护性。然而,策略模式也有其局限性,需要在具体应用场景中权衡其优缺点,合理使用。

九、注意事项

在使用策略模式时,需要注意以下几点:

  1. 策略类数量控制:避免创建过多的策略类,以免增加系统的复杂性。可以通过合理的策略划分和合并来减少策略类的数量。
  2. 策略切换逻辑:确保策略切换的逻辑正确无误,避免出现策略切换错误或遗漏的情况。
  3. 策略配置管理:对于需要动态配置策略的场景,需要提供合理的策略配置管理机制,方便用户进行策略的选择和切换。

十、未来展望

随着技术的不断发展和业务场景的日益复杂,策略模式将在更多领域得到应用
十一、策略模式与其他设计模式的协同

策略模式经常与其他设计模式结合使用,以构建更健壮和灵活的系统。例如,策略模式可以与工厂模式结合,用于创建具体的策略对象。工厂模式可以根据需要动态地生成并返回策略对象,从而进一步解耦策略的选择和创建过程。

十二、策略模式的性能考虑

虽然策略模式提供了高度的灵活性和可扩展性,但在某些情况下,频繁地切换策略可能会带来性能开销。因此,在设计系统时,需要权衡策略模式带来的好处和可能带来的性能损失,确保系统的整体性能满足要求。

十三、策略模式的适用与不适用的场景

策略模式适用于那些需要根据不同情况使用不同算法或行为的场景。例如,当有多种排序算法可供选择时,或者当系统需要支持多种支付方式时,策略模式都是很好的选择。然而,对于那些算法或行为相对固定,不需要频繁更改的场景,使用策略模式可能会增加不必要的复杂性。

十四、代码示例扩展

在之前的示例中,我们演示了如何使用策略模式实现支付功能。现在,我们可以进一步扩展这个示例,加入更多具体的策略实现,如第三方支付策略、分期付款策略等。同时,我们可以考虑在支付上下文类中添加更多的逻辑,如验证支付信息的有效性、处理支付异常等。

十五、策略模式的实际应用案例

以电商平台的促销活动为例,不同的促销活动可能需要不同的折扣策略或优惠策略。通过使用策略模式,我们可以为每种促销活动定义一个具体的策略类,并在活动开始时动态地选择并应用相应的策略。这样,当平台需要推出新的促销活动或调整现有活动的策略时,只需添加或修改相应的策略类即可,无需修改整个促销系统的代码。

十六、策略模式的改进与扩展

在实际应用中,我们可以对策略模式进行改进和扩展,以满足更复杂的需求。例如,我们可以引入策略链模式,使得多个策略可以按照一定的顺序依次执行。此外,我们还可以考虑使用上下文映射来管理策略与上下文之间的关联关系,以便更方便地进行策略的选择和切换。

十七、策略模式的挑战与解决方案

虽然策略模式带来了很多好处,但在实际应用中也可能会遇到一些挑战。例如,当策略数量众多且复杂时,管理和维护这些策略可能会变得困难。为了解决这个问题,我们可以采用一些策略管理的最佳实践,如使用配置文件或数据库来存储和管理策略信息,或者开发专门的策略管理工具来简化策略的管理过程。

十八、策略模式的学习建议

学习策略模式时,建议从理解其基本概念和结构开始,然后通过编写简单的示例代码来加深理解。在掌握了基本用法后,可以尝试在实际项目中应用策略模式,并思考如何与其他设计模式结合使用来构建更健壮和灵活的系统。同时,也可以阅读一些关于策略模式的优秀文章和书籍,以获取更多的学习资源和灵感。

十九、策略模式的未来发展趋势

随着软件技术的不断发展和业务场景的不断变化,策略模式将继续发挥重要作用。未来,我们可以期待策略模式在更多领域得到应用,并与新的技术趋势和设计模式相结合,为构建更高效、更灵活的软件系统提供支持。

二十、总结与展望

策略模式是一种强大而灵活的设计模式,它允许我们在运行时动态地改变对象的行为。通过深入理解和掌握策略模式的概念、结构、实现方式以及优缺点,我们可以更好地应用它来解决实际问题并提升系统的可维护性和可扩展性。随着技术的不断进步和业务需求的不断变化,我们有理由相信策略模式将在未来继续发挥重要作用,并与其他设计模式和技术趋势共同推动软件行业的发展。

相关文章:

【设计模式】Java 设计模式之模板策略模式(Strategy)

策略模式详解:模式结构、实现与应用场景 一、策略模式概述 策略模式是一种行为设计模式,它使得算法可以独立于使用它的客户端变化。策略模式使得算法可以在运行时切换,从而增强了系统的灵活性和可维护性。在策略模式中,我们定义…...

SpringBoot项目前端Vue访问后端(图片静态资源) 配置

静态资源配置 Configuration public class WebMvcConfig extends WebMvcConfigurationSupport {Value("${file.save-path}")private String fileSavePath;Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {//映射本地文件夹registry…...

colab中数据集保存到drive与取出的方法

from google.colab import drive drive.mount(/content/drive) 一、下载数据集 from datasets import load_dataset max_length 32 # Maximum length of the captions in tokens coco_dataset_ratio 50 # 50% of the COCO2014 dataset# Load the COCO2014 dataset for tr…...

React 应该如何学习?

学习 React 是现代 Web 前端开发中的重要一步,因为它是一个流行且强大的 JavaScript 库,用于构建用户界面。React 的学习过程需要掌握一系列的概念、技术和最佳实践。 1. 基础知识 1.1 HTML、CSS 和 JavaScript React 本质上是一个 JavaScript 库&…...

跨平台无缝操作:ShareMouse让多电脑协同更高效

ShareMouse是一款功能强大的鼠标和键盘共享软件,它支持多台计算机之间的无缝连接,让用户能够通过一套键鼠设备轻松控制多台电脑,提高工作效率。此外,ShareMouse还具备剪贴板共享、文件拖放等功能,实现不同计算机间的便…...

Vue使用pandoc-wasm进行各格式转换

前端使用pandoc-wasm的问题和建议 docx转md npm install --save pandoc-wasmimport { Pandoc } from "pandoc-wasm";const pandoc new Pandoc()pandoc.init().then(async (pandoc) > {const result await pandoc.run({text: "Some input text",opti…...

springboot284基于HTML5的问卷调查系统的设计与实现

问卷调查系统的设计与实现 摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,问卷信息因为其管理内容繁杂,管理数量繁多导…...

AI短视频制作一本通:文本生成视频、图片生成视频、视频生成视频

第一部分:文本生成视频 1. 文本生成视频概述 随着人工智能(AI)技术的飞速发展,视频制作领域也迎来了创新的浪潮。文本生成视频是其中的一项令人激动的进展,它利用自然语言处理技术将文本内容转化为视频。这项技术在广…...

详谈分布式事务

目录 前言 1.sharding的分布式事务 2.分布式事务的产生原因 3.分布式事务的解决方案 3.1.DTP模型 3.2.分阶段提交 3.3.TCC模式 3.4.可靠消息服务 3.5.AT模式 3.6.Seata 前言 本文是前面一篇文章聊了基于sharding的分库分表后拓展出来的关于分布式事务的讨论&#xf…...

Java基础知识八股

1.为什么静态方法无法调用非静态方法? 回答:因为静态方法是随着类的加载而加载,而非静态方法则是随着类的实例化才会被加载,生存周期不一样,所以静态方法的生命周期更长 2.Java–内部类持有外部类导致内存泄露的原因和…...

【Linux】网络基础一

网络基础一 1.计算机网络背景1.1 网络发展1.2 认识 “协议” 2.网络协议初识2.1 协议分层2.2 OSI七层模型2.3 TCP/IP五层(或四层)模型 3. 网络传输基本流程3.1 网络传输流程图 4.数据包封装和分用5.网络中的地址管理 从今天开始我们将要从系统横跨到网络的学习了,因…...

Redis-2 Redis基础数据类型与基本使用

高级Redis应用进阶 一站式Redis解决方案-Redis-2 Redis基础数据类型与基本使用 源代码在GitHub - 629y/food-social-contact-parent: redis项目-美食社交APP 1. Redis基本数据类型 1.字符串(strings) set username zhangsan get username mset age 18 …...

python提取身份证中的生日和性别

1.代码 def sfzAnalysis(idNum):#检查身份证长度是否正确if len(idNum)!18:raise ValueError("身份证号码长度不正确,请输入一个18位的身份证号码。")#raise关键字在Python中有多种用途,主要涉及异常的抛出和错误处理#提取出生日期year idN…...

opencv 傅里叶变换(低通滤波 + 高通滤波)

文章目录 1、傅里叶变换2、通过numpy实现3、高通滤波器5、通过opencv实现傅里叶变换6、低通滤波器7、C实现傅里叶变换 1、傅里叶变换 时域分析:以时间作为参照物,世间万物都是随着时间变化而变化,并且不会停止 频域分析:认为世间万…...

Educational Codeforces Round 163 (Rated for Div. 2)(A,B,C,D,E)

比赛链接 好忙好忙好忙,慢慢补老比赛的题解了。 这场没啥算法,全是思维。有也是BFS,屎。 A. Special Characters 题意: 您将得到一个整数 n n n 。 您的任务是构建一串大写的拉丁字母。此字符串中必须正好有 n n n 个特殊字…...

索引常见面试题

面试中,MySQL 索引相关的问题基本都是一系列问题,都是先从索引的基本原理,再到索引的使用场景,比如: 索引底层使用了什么数据结构和算法?为什么 MySQL InnoDB 选择 Btree 作为索引的数据结构?什…...

【Unity】旋转的尽头是使用四元数让物体旋转

// 导入必要的命名空间 using System.Collections; using System.Collections.Generic; using UnityEngine;// 创建一个名为 RotateObj 的 MonoBehaviour 类,该类可以附加到 Unity 中的游戏对象上并控制其行为 public class RotateObj : MonoBehaviour {// Update 函…...

哔哩哔哩秋招Java二面

前言 作者:晓宜 个人简介:互联网大厂Java准入职,阿里云专家博主,csdn后端优质创作者,算法爱好者 一面过后面试官叫我别走,然后就直接二面,二面比较简短,记录一下,希望可以…...

OSPF特殊区域(stub\nssa)

stub区域——只有1类、2类、3类;完全stub区域——只有1类、2类 NSSA区域:本区域将自己引入的外部路由发布给其他区域,但不需要接收其他区域的路由 在NSSA区域的路由器上,引入外部路由时,不会转换成5类LSA&#xff0c…...

全球首位AI程序员诞生,将会对程序员的影响有多大?

随着全球首位AI程序员Devin的诞生,人工智能技术在编程领域的应用引发了广泛的讨论和思考。这一事件不仅标志着AI技术在软件开发领域的一大步进展,也引起了人们对未来编程职业发展的广泛关注。那么,AI程序员的出现究竟会对程序员的职业生涯产生…...

XML Group端口详解

在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

EtherNet/IP转DeviceNet协议网关详解

一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...

Ubuntu系统复制(U盘-电脑硬盘)

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

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...