Java设计模式:行为型模式→策略模式

Java 策略模式详解

1. 定义

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列的算法,将每一个算法封装起来,并使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户。通过这种模式,可以在运行时选择特定的算法,从而实现灵活的行为。

2. 基本思想

策略模式的基本思想是将算法的实现与使用算法的环境相分离。使用策略模式,客户端可以根据具体需要选择的策略(算法)而不是硬编码到类中,并且可以在运行时根据不同的条件进行选择。通过这种方式,可以避免使用多重的条件判断语句,增强代码的可读性和可维护性。

3. 基本原理

策略模式主要由以下几个组成部分构成:

  • 策略接口(Strategy):定义所有支持的算法接口。
  • 具体策略类(Concrete Strategy):实现具体的算法。
  • 上下文类(Context):持有一个策略对象的引用,并通过该对象调用具体的策略算法。
  • 客户端(Client):使用上下文类来选择和执行具体策略。
    在这里插入图片描述

更多实用资源:

http://sj.ysok.net/jydoraemon 访问码:JYAM

4. 实现方式

4.1 基本实现

4.1.1 策略接口

首先定义一个策略接口,定义算法的标准:

public interface PaymentStrategy {void pay(int amount);
}
4.1.2 具体策略类

实现具体的支付方式,例如信用卡支付和 PayPal 支付:

public class CreditCardPayment implements PaymentStrategy {private String cardNumber;public CreditCardPayment(String cardNumber) {this.cardNumber = cardNumber;}@Overridepublic void pay(int amount) {System.out.println("Paid " + amount + " using Credit Card: " + cardNumber);}
}public class PayPalPayment implements PaymentStrategy {private String email;public PayPalPayment(String email) {this.email = email;}@Overridepublic void pay(int amount) {System.out.println("Paid " + amount + " using PayPal: " + email);}
}
4.1.3 上下文类

定义上下文类,并持有一个策略对象的引用:

public class PaymentContext {private PaymentStrategy paymentStrategy;public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void executePayment(int amount) {paymentStrategy.pay(amount);}
}
4.1.4 客户端代码

客户端代码,通过上下文类选择支付策略并执行:

public class Client {public static void main(String[] args) {PaymentContext paymentContext = new PaymentContext();// 使用信用卡支付PaymentStrategy creditCard = new CreditCardPayment("1234-5678-9876-5432");paymentContext.setPaymentStrategy(creditCard);paymentContext.executePayment(100); // 支付 100 单位// 使用 PayPal 支付PaymentStrategy payPal = new PayPalPayment("user@example.com");paymentContext.setPaymentStrategy(payPal);paymentContext.executePayment(200); // 支付 200 单位}
}

4.2 代码分析

  • 策略接口(PaymentStrategy):定义了所有具体支付策略实现的方法。
  • 具体策略类(CreditCardPayment 和 PayPalPayment):实现了不同的支付方式,具体执行支付逻辑。
  • 上下文类(PaymentContext):通过设置具体策略并执行支付,客户端不需要关心具体的支付实现。
  • 客户端:能够灵活选择和使用不同支付方式,体现策略的可替换性。

5. 工作流程

  1. 定义策略接口:创建一个接口以定义支持的策略算法。
  2. 实现具体策略类:编写不同的具体策略,分别实现策略接口。
  3. 创建上下文类:上下文类持有对策略对象的引用,负责调用策略的算法。
  4. 客户端选择策略:客户端通过上下文类来动态选择策略。

6. 变种

  1. 环境策略模式:在运行时,根据环境变化选择不同的策略,这是策略模式的常见变种。
  2. 组合策略模式:将多个策略组合在一起,形成复合的策略。

7. 实际应用

策略模式在实际开发中广泛应用,以下是一些典型的应用场景:

  1. 支付系统:根据不同支付方式的选择,选用不同的支付策略实现。
  2. 排序算法:采用不同的排序算法(快速排序、归并排序等)来处理数据,基于不同的条件选择最优排序策略。
  3. 图形处理:在图形应用中,根据不同的绘制需求使用不同的绘制算法。

8. 使用场景

使用策略模式的场景包括:

  • 当一个类需要根据不同条件选择算法时。
  • 需要在运行时动态更换算法实现时。
  • 避免在类中使用大量的条件语句时,能够提高代码的可读性和可维护性。

9. 优缺点

优点

  1. 灵活性:可以在运行时选择和切换策略。
  2. 避免条件判断:避免使用大量条件语句,提高代码的清晰度。
  3. 符合开闭原则:新的策略可以在不修改现有代码的情况下添加。

缺点

  1. 增加代码复杂性:增加了类的数量,使得系统结构更加复杂。
  2. 客户端需要了解策略:客户端需要知道许多策略的具体实现,以便于选择合适的策略。

10. 最佳实践

  1. 选择合适的接口设计:使策略的接口尽量简洁,便于理解和使用。
  2. 合理管理策略:在上下文中管理策略,避免混乱。
  3. 务必遵循单一职责原则:每个策略应当负责一个独立的功能,确保可维护性。

11. 注意事项

  1. 避免滥用策略模式:在不适合的情况下使用策略模式会导致系统过度复杂。
  2. 确保策略的独立性:策略之间应当保持独立,避免相互干扰。
  3. 考虑性能影响:在策略数量较多时,过多的策略切换可能会对性能产生一定影响。

12. 常见的误区

  • 策略模式仅能处理简单场景:策略模式不仅适用于简单的情况,也可以解决复杂的业务逻辑。
  • 认为策略模式会增加不必要的复杂性:在复杂的条件分支下,使用策略模式可以提高代码的清晰度。

13. 常见问题

  • 策略模式的核心组成部分是什么?

    • 策略模式的核心组成部分包括策略接口、具体策略类、上下文类和客户端。
  • 如何判断使用策略模式的适用性?

    • 当需要在运行时选择算法,并希望避免在类中使用复杂的条件判断时,可以考虑使用策略模式。
  • 策略模式与状态模式的区别是什么?

    • 策略模式用于选择算法,行为由对象决定;状态模式用于改变对象的状态,行为依赖于当前状态。

14. 总结

策略模式是一种极为灵活且有效的设计模式,适合在需要根据不同条件选择算法或行为的场景中应用。通过把不同的算法进行封装,并相互替换,策略模式增强了代码的可复用性和可维护性。在实际开发中,理解策略模式的基本原理、优缺点及使用场景,将帮助开发者设计出更具灵活性和可扩展性的Java应用程序。合理运用策略模式,可以显著提升系统的设计质量,为开发者提供更高效的架构设计方案。

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

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

相关文章

linux通过deb包安装(命令模式)

通过下载deb包安装Chrome浏览器 - lyy19s Wikihttps://lyy1119.github.io/%E8%BD%AF%E4%BB%B6%E4%BD%BF%E7%94%A8/Linux/InstallChrome/

C基础寒假练习(4)

输入带空格的字符串&#xff0c;求单词个数、 #include <stdio.h> // 计算字符串长度的函数 size_t my_strlen(const char *str) {size_t len 0;while (str[len] ! \0) {len;}return len; }int main() {char str[100];printf("请输入一个字符串: ");fgets(…

Android View 的事件分发机制解析

前言&#xff1a;当一个事件发生时&#xff08;例如触摸屏幕&#xff09;&#xff0c;事件会从根View&#xff08;通常是Activity的布局中的最顶层View&#xff09;开始&#xff0c;通过一个特定的路径传递到具体的View&#xff0c;这个过程涉及到三个关键的阶段&#xff1a;事…

WPS数据分析000005

目录 一、数据录入技巧 二、一维表 三、填充柄 向下自动填充 自动填充选项 日期填充 星期自定义 自定义序列 1-10000序列 四、智能填充 五、数据有效性 出错警告 输入信息 下拉列表 六、记录单 七、导入数据 ​编辑 八、查找录入 会员功能 Xlookup函数 VL…

【Spring】Spring启示录

目录 前言 一、示例程序 二、OCP开闭原则 三、依赖倒置原则DIP 四、控制反转IOC 总结 前言 在软件开发的世界里&#xff0c;随着项目的增长和需求的变化&#xff0c;如何保持代码的灵活性、可维护性和扩展性成为了每个开发者必须面对的问题。传统的面向过程或基于类的设计…

爬虫基础之爬取某基金网站+数据分析

声明: 本案例仅供学习参考使用&#xff0c;任何不法的活动均与本作者无关 网站:天天基金网(1234567.com.cn) --首批独立基金销售机构-- 东方财富网旗下基金平台! 本案例所需要的模块: 1.requests 2.re(内置) 3.pandas 4.pyecharts 其他均需要 pip install 模块名 爬取步骤: …

set集合

set集合 Set系列集合&#xff1a; 无序&#xff1a;存取顺序不一致 不重复&#xff1a;可以去除重复 无索引&#xff1a;没有带索引的方法&#xff0c;所以不能使用普通for循环遍历&#xff0c;也不能通过索引来获取元素 可以看出set是无序的存和打印的顺序不一样 Set接中的…

借DeepSeek-R1东风,开启创业新机遇

DeepSeek-R1的崛起 DeepSeek-R1的推出引发了广泛关注&#xff0c;在AI领域引起了一阵旋风。作为新一代的智能模型&#xff0c;它在多项任务中表现出了卓越的能力。普通人可以借助这个强大的工具&#xff0c;开启属于自己的创业之路&#xff0c;抓住时代带来的机遇。 内容创作…

项目集成Nacos

文章目录 1.环境搭建1.创建模块 sunrays-common-cloud-nacos-starter2.目录结构3.pom.xml4.自动配置1.NacosAutoConfiguration.java2.spring.factories 5.引入cloud模块通用依赖 2.测试1.创建模块 sunrays-common-cloud-nacos-starter-demo2.目录结构3.pom.xml4.application.ym…

系统安全及应用

一&#xff1a;账号安全控制 1.1 系统账号清理 1.1.1 将非登陆用户的Shell 设置为 /sbin/nologin (设置为这个解释器&#xff0c;禁止用户登陆&#xff09; [rootlocalhost ~]# usermod -s /sbin/nologin zhangsan #将用户zhangsan 的登录解释器 设置为 /sbin/n…

从源码深入理解One-API框架:适配器模式实现LLM接口对接

1. 概述 one-api 是一个开源的 API 框架&#xff0c;基于go语言开发&#xff0c;旨在提供统一的接口调用封装&#xff0c;支持多种 AI 服务平台的集成。通过 Gin 和 GORM 等框架&#xff0c;框架简化了多种 API 服务的调用流程。通过适配器模式实现了与多种 大模型API 服务的集…

[权限提升] 操作系统权限介绍

关注这个专栏的其他相关笔记&#xff1a;[内网安全] 内网渗透 - 学习手册-CSDN博客 权限提升简称提权&#xff0c;顾名思义就是提升自己在目标系统中的权限。现在的操作系统都是多用户操作系统&#xff0c;用户之间都有权限控制&#xff0c;我们通过 Web 漏洞拿到的 Web 进程的…

多模态论文笔记——ViViT

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细解读多模态论文《ViViT: A Video Vision Transformer》&#xff0c;2021由google 提出用于视频处理的视觉 Transformer 模型&#xff0c;在视频多模态领域有…

【深度之眼cs231n第七期】笔记(三十一)

目录 强化学习什么是强化学习&#xff1f;马尔可夫决策过程&#xff08;MDP&#xff09;Q-learning策略梯度SOTA深度强化学习 还剩一点小尾巴&#xff0c;还是把它写完吧。&#xff08;距离我写下前面那行字又过了好几个月了【咸鱼本鱼】&#xff09;&#xff08;汗颜&#xff…

[免费]基于Python的Django博客系统【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的基于Python的Django博客系统&#xff0c;分享下哈。 项目视频演示 【免费】基于Python的Django博客系统 Python毕业设计_哔哩哔哩_bilibili 项目介绍 随着互联网技术的飞速发展&#xff0c;信息的传播与…

【Docker】Docker入门了解

文章目录 Docker 的核心概念Docker 常用命令示例&#xff1a;构建一个简单的 C 应用容器1. 创建 C 应用2. 创建 Dockerfile3. 构建镜像4. 运行容器 Docker 优势学习 Docker 的下一步 **一、Docker 是什么&#xff1f;****为什么 C 开发者需要 Docker&#xff1f;** **二、核心概…

如何跨互联网adb连接到远程手机-蓝牙电话集中维护

如何跨互联网adb连接到远程手机-蓝牙电话集中维护 --ADB连接专题 一、前言 随便找一个手机&#xff0c;安装一个App并简单设置一下&#xff0c;就可以跨互联网的ADB连接到这个手机&#xff0c;从而远程操控这个手机做各种操作。你敢相信吗&#xff1f;而这正是本篇想要描述的…

基于java线程池和EasyExcel实现数据异步导入

基于java线程池和EasyExcel实现数据异步导入 2.代码实现 2.1 controller层 PostMapping("import")public void importExcel(MultipartFile file) throws IOException {importService.importExcelAsync(file);}2.2 service层 Resource private SalariesListener sa…

linux asio网络编程理论及实现

最近在B站看了恋恋风辰大佬的asio网络编程&#xff0c;质量非常高。在本章中将对ASIO异步网络编程的整体及一些实现细节进行完整的梳理&#xff0c;用于复习与分享。大佬的博客&#xff1a;恋恋风辰官方博客 Preactor/Reactor模式 在网络编程中&#xff0c;通常根据事件处理的触…

Python爬虫学习第三弹 —— Xpath 页面解析 实现无广百·度

早上好啊&#xff0c;大佬们。上回使用 Beautiful Soup 进行页面解析的内容是不是已经理解得十分透彻了~ 这回我们再来尝试使用另外一种页面解析&#xff0c;来重构上一期里写的那些代码。 讲完Xpath之后&#xff0c;小白兔会带大家解决上期里百度搜索的代码编写&#xff0c;保…