Java二十三种设计模式-策略模式(13/23)

news2025/1/14 1:04:43

策略模式:灵活算法的替换与扩展

引言

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

基础知识,java设计模式总体来说设计模式分为三大类:

(1)创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

(2)结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

(3)行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

第一部分:策略模式概述

1.1 定义与用途

策略模式的基本定义

策略模式是一种行为型设计模式,它允许在运行时选择算法的行为,将算法封装在独立的策略类中,从而让算法可以互相替换。

解释为何需要策略模式

  • 算法的多样性:在许多应用中,可能需要根据不同的条件执行不同的算法或行为。
  • 算法的独立性:策略模式让算法独立于使用它们的客户端,使得算法可以独立变化和扩展。
  • 避免多重条件语句:使用策略模式可以避免在客户端代码中使用复杂的条件语句来决定使用哪个算法。

1.2 策略模式的组成

策略接口(Strategy Interface)

  • 定义:定义所有支持的算法的公共接口。
  • 角色:作为所有具体策略类的父接口,确保它们具有一致的方法签名。

具体策略(Concrete Strategy)

  • 定义:实现策略接口的具体算法类。
  • 角色:提供策略接口中定义的算法的具体实现。

上下文(Context)

  • 定义:使用策略接口与具体策略交互的类。
  • 角色:维持一个对策略对象的引用,并在运行时根据需要切换策略。

客户端(Client)

  • 角色:使用上下文对象来访问策略对象提供的服务。
  • 职责:客户端不直接与具体策略类交互,而是通过上下文来间接使用策略。

角色之间的交互

  • 客户端与上下文:客户端通过上下文来请求服务,上下文负责将请求委托给当前策略。
  • 上下文与具体策略:上下文通过内部的策略引用来调用具体策略的算法。

策略模式通过定义清晰的接口和角色,提供了一种灵活的方式来管理和使用不同的算法。在下一部分中,我们将通过Java代码示例来展示策略模式的具体实现。

第二部分:策略模式的实现

2.1 Java实现示例

以下是使用Java语言实现策略模式的代码示例。假设我们有一个简单的计算系统,需要根据不同的策略来执行加、减、乘、除操作。

// 策略接口
interface Strategy {
    int execute(int a, int b);
}

// 具体策略:加法
class AddStrategy implements Strategy {
    public int execute(int a, int b) {
        return a + b;
    }
}

// 具体策略:减法
class SubtractStrategy implements Strategy {
    public int execute(int a, int b) {
        return a - b;
    }
}

// 上下文
class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int a, int b) {
        return strategy.execute(a, b);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Context context = new Context(new AddStrategy());
        System.out.println("Add: 10 + 5 = " + context.executeStrategy(10, 5));

        context.setStrategy(new SubtractStrategy());
        System.out.println("Subtract: 10 - 5 = " + context.executeStrategy(10, 5));
    }
}

 

2.2 策略模式中的角色和职责

策略接口(Strategy)

  • 职责:定义所有策略类必须遵循的公共接口,通常包含一个或多个执行算法的方法。

具体策略(Concrete Strategy)

  • 职责:实现策略接口,提供具体的算法实现。可以有多个具体策略类,每个类实现不同的算法。

上下文(Context)

  • 职责
    • 作为策略接口与具体策略的中介,存储对某个策略对象的引用。
    • 根据实际的策略对象来调用相应的算法方法。

客户端(Client)

  • 职责
    • 通过上下文来使用策略对象,不直接与具体策略类交互。
    • 可以根据需要通过上下文来切换不同的策略。

相互作用

  • 客户端与上下文:客户端创建上下文对象,并根据需要设置具体的策略对象。
  • 上下文与具体策略:上下文在执行操作时,委托给内部维护的策略对象来完成。
  • 客户端与具体策略:客户端不直接与具体策略交互,所有的交互都通过上下文来完成。

策略模式提供了一种灵活的方式来替换算法或行为,使得算法的变化独立于使用算法的客户。在下一部分中,我们将探讨策略模式的使用场景。

第三部分:策略模式的使用场景

3.1 需要替换算法或行为的场景

策略模式在需要根据不同条件替换算法或行为时非常有用。以下是一些具体的应用场景:

  • 用户自定义设置:在应用程序中,用户可能希望根据自己的偏好选择不同的排序或搜索算法。
  • 游戏AI:在游戏开发中,不同的敌人或角色可能使用不同的行为策略。
  • 支付方式:电子商务平台可能需要支持多种支付方式,如信用卡、PayPal、微信支付等。

策略模式的应用:

  • 条件分支的替代:使用策略模式可以替代大量的条件分支语句,使代码更加清晰。
  • 动态替换:策略模式允许在运行时根据条件动态替换算法,提高了系统的灵活性。

应用实例:

  • 文本编辑器:文本编辑器可能提供不同的文本格式化策略,如粗体、斜体、下划线等。

3.2 需要扩展新算法的场景

当系统需要扩展新算法时,策略模式提供了显著的优势,因为它允许开发者在不修改现有代码的基础上添加新的算法。

  • 无需修改现有代码:遵循开闭原则,对扩展开放,对修改封闭。
  • 算法的独立性:每个算法都是独立的类,可以独立开发和测试。

策略模式的优势:

  • 易于添加新策略:添加新策略时,只需实现策略接口并创建新的策略类。
  • 解耦算法与使用场景:策略模式将算法的实现与使用场景解耦,使得两者可以独立变化。

应用实例:

  • 图形渲染:图形渲染程序可能需要根据不同的对象类型使用不同的渲染策略,如点、线、多边形等。

通过策略模式,开发者可以在不同的场景下灵活地替换或扩展算法,同时保持代码的整洁和可维护性。在下一部分中,我们将讨论策略模式的优点与缺点。

第四部分:策略模式的优点与缺点

4.1 优点

提高灵活性

  • 动态替换:策略模式允许在运行时根据条件动态替换算法,提供了高度的灵活性。

增强可扩展性

  • 遵循开闭原则:遵循软件设计的开闭原则,对扩展开放,对修改封闭,便于添加新算法。

降低耦合度

  • 解耦算法与使用:将算法与使用算法的代码解耦,使得它们可以独立变化。

简化单元测试

  • 独立测试:由于算法的独立性,可以更容易地对策略进行单元测试。

易于维护和复用

  • 算法复用:相同的策略可以在不同的上下文中复用,减少了代码重复。

4.2 缺点

增加系统复杂性

  • 类的数量:策略模式可能会增加系统中类的数量,每个策略都需要一个独立的类。

增加设计难度

  • 理解难度:对于不熟悉策略模式的开发者,理解这种模式可能有一定难度。

性能考虑

  • 性能开销:在某些情况下,策略模式可能会引入额外的性能开销,尤其是在策略选择和委托过程中。

过度使用

  • 滥用风险:如果过度使用策略模式,可能会导致设计过度复杂化,例如,当算法差异很小或算法数量过多时。

策略管理

  • 策略选择:在策略数量很多的情况下,选择合适的策略可能变得复杂。

客户端负担

  • 客户端责任:客户端需要了解不同的策略并作出选择,这可能会增加客户端的负担。

策略模式是一种强大的设计模式,它通过将算法封装在独立的策略类中,提高了系统的灵活性和可扩展性。然而,合理使用策略模式并避免其缺点是至关重要的。了解其优点和缺点可以帮助开发者根据具体需求和场景选择最合适的设计模式。在实际开发中,应根据具体情况灵活运用策略模式,以达到最佳的设计效果。

第五部分:策略模式与其他模式的比较

5.1 与状态模式的比较

状态模式

  • 定义:状态模式允许一个对象在其内部状态改变时改变其行为,看起来好像改变了其类。
  • 使用场景:适用于对象状态较多且不同状态行为有明显差异的情况。

策略模式

  • 定义:策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互换。
  • 使用场景:适用于需要根据不同条件选择不同算法或策略的情况。

对比

  • 关注点:状态模式关注于对象状态的变化以及状态变化导致的行为变化,而策略模式关注于算法或策略的替换。
  • 使用目的:状态模式用于处理状态变化,策略模式用于处理算法的多样性和可替换性。

5.2 与命令模式的对比

命令模式

  • 定义:命令模式将请求或操作封装为一个对象,从而使你可以用不同的请求对客户进行参数化。
  • 使用场景:适用于需要将操作请求排队、记录、撤销或重做的情况。

策略模式

  • 定义:如上所述,策略模式用于定义算法族并使它们可以互换。

对比

  • 执行操作:命令模式关注于执行操作的封装和调度,策略模式关注于算法的替换和选择。
  • 使用目的:命令模式用于命令的封装和调用,策略模式用于算法的封装和使用。

其他区别

  • 组合使用:策略模式可以与命令模式结合使用,例如,将不同的策略作为命令的参数传递。
  • 职责分配:命令模式中的对象通常包含执行操作的所有信息,而策略模式将算法的实现与使用分离。

通过比较策略模式与状态模式和命令模式,我们可以更清晰地理解每种模式的独特用途和优势。在实际应用中,根据具体需求和场景选择合适的设计模式是非常重要的。在下一部分中,我们将提供策略模式的最佳实践和建议。

第六部分:策略模式的最佳实践和建议

6.1 最佳实践

保持策略接口的单一职责

  • 单一职责原则:确保策略接口只定义一个算法或行为,避免将多个不同的行为混合在一个接口中。

定义清晰的策略接口

  • 清晰的合同:策略接口应该清晰地定义策略的合同,让实现者容易理解和实现。

避免策略类的过度复杂

  • 简单实现:尽量保持策略类的实现简单,避免过度复杂的逻辑。

使用上下文封装策略逻辑

  • 封装变化:使用上下文类封装策略的逻辑,包括策略的选择和切换。

允许运行时策略替换

  • 动态行为:策略模式应该允许在运行时根据条件或用户输入替换策略。

提供默认策略

  • 默认实现:为避免在没有明确策略时出现错误,提供一个默认的策略实现。

6.2 避免滥用

避免策略类数量过多

  • 适度使用:避免因为过度使用策略模式而产生大量的策略类,这可能会使系统变得复杂和难以管理。

避免策略接口定义不当

  • 合理定义:确保策略接口的定义合理,既不要太宽泛也不要太狭窄。

避免忽视性能影响

  • 性能考量:在设计策略模式时,考虑策略选择和切换可能带来的性能影响。

6.3 替代方案

使用函数指针或函数引用

  • 简化实现:在某些编程语言中,可以使用函数指针或函数引用来简化策略模式的实现。

使用委托或回调

  • 回调机制:在不支持策略模式的环境下,可以使用委托或回调机制来达到类似的效果。

使用状态模式

  • 状态变化:当对象的状态变化需要改变其行为时,可以考虑使用状态模式。

使用组合模式

  • 部分-整体结构:当需要表示对象的部分-整体层次结构时,可以使用组合模式。

使用适配器模式

  • 接口适配:当需要将一个类的接口适配到另一个接口时,可以使用适配器模式。

策略模式是一种强大的设计模式,可以在运行时动态地替换算法或行为,提高了系统的灵活性和可扩展性。然而,合理使用策略模式并避免其缺点是至关重要的。了解其替代方案可以帮助开发者根据具体需求和场景选择最合适的设计模式。在实际开发中,应根据具体情况灵活运用策略模式,以达到最佳的设计效果。

结语

策略模式提供了一种灵活的方式来替换和扩展算法,使得系统更加灵活和可扩展。通过本文的深入分析,希望读者能够对策略模式有更全面的理解,并在实际开发中做出合理的设计选择。

 博主还写了其他Java设计模式关联文章,请各位大佬批评指正:

(一)创建型模式(5种):

Java二十三种设计模式-单例模式(1/23)

Java二十三种设计模式-工厂方法模式(2/23)

Java二十三种设计模式-抽象工厂模式(3/23)

Java二十三种设计模式-建造者模式(4/23)

Java二十三种设计模式-原型模式(5/23)

(二)结构型模式(7种): 

Java二十三种设计模式-适配器模式(6/23)

Java二十三种设计模式-装饰器模式(7/23)

Java二十三种设计模式-代理模式(8/23)

Java二十三种设计模式-外观模式(9/23)

Java二十三种设计模式-桥接模式(10/23)

Java二十三种设计模式-组合模式(11/23)

Java二十三种设计模式-享元模式(12/23)

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

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

相关文章

menuconfig+Kconfig的简单配置

目录 1.背景 2.管理方案 2.1:.h中直接定义 2.2:.batCmake 2.3:Kconfig 2.3.1 环境安装 2.3.2 代码 2.3.2.1 目录结构 2.3.2.2 ble目录下的Kconfig 2.3.2.3 hardware目录下的Kconfig 2.3.2.4 rtos目录下的Kconfig 2.3.2.5 根目录 …

【性能】console.log引起内存泄漏

如下代码中的console.log会引起内存泄漏 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Example<…

降级、熔断、限流学习笔记

1. 面对高流量出现故障的原因 由于依赖的资源或者服务不可用&#xff0c;最终导致整体服务宕机。在电商系统中就可能由于数据库访问缓慢&#xff0c;导致整体服务不可用。 乐观地预估了可能到来的流量&#xff0c;当有超过系统承载能力的流量到来时&#xff0c;系统不堪重负&a…

Vue.js 3.x 必修课|008|计算属性:提高代码服用性和可维护性

欢迎关注公众号:CodeFit。 创作不易,如果你觉得这篇文章对您有帮助,请不要忘了 点赞、分享 和 关注,为我的 持续创作 提供 动力! 欢迎订阅《Vue 3.x 必修课| 2024》:http://t.csdnimg.cn/hHRrM 精品内容,物超所值,一杯咖啡的价格(9.9 元)只为持续创作提供动力。 在 …

【AI】人工智能时代,程序员如何保持核心竞争力?

目录 程序员在AI时代的应对策略1. 引言2. AI在编程领域的影响2.1 AI辅助编程工具的现状2.2 AI对编程工作的影响2.3 程序员的机遇与挑战 3. 深耕细作&#xff1a;专注领域的深度学习3.1 专注领域的重要性3.2 深度学习的策略3.2.1 选择合适的领域3.2.2 持续学习和研究3.2.3 实践与…

【PXE+kickstart】linux网络服务之自动装机

PXE&#xff1a; 简介&#xff1a;PXE(Preboot execute environment 是一种能够让计算机通过网络启动的引导方式&#xff0c;只要网卡支持PXE协议即可使用Kickstart 是一种无人值守的安装方式&#xff0c;工作原理就是预先把原本需要运维人员手工填写的参数保存成一个 ks.cfg 文…

centos7安装 ES集群 elasticsearch

这里写自定义目录标题 编写启动脚本 elasticsearch.sh启动可能报错&#xff1a;elasticsearch 7.10启动报错 bootstrap checks failed解决方法问题原因&#xff1a;注意 退出xshell&#xff0c;重新登录&#xff1a; 上面两个配置项改完后&#xff0c;ES启动用户(es 或root) **…

Debian | 更换 Gnome 至 Xfce4

Debian | 更换 Gnome 至 Xfce4 更新源 sudo apt update && sudo apt upgrade安装 xfce4 sudo apt install xfce4我选择 lightdm&#xff0c;回车 切换桌面 sudo update-alternatives --config x-session-manager输入 xfce 所在序号&#xff0c;我这里是 3 卸载 …

洛谷 P1560 [USACO5.2]蜗牛的旅行Snail Trails(c++)

describe 蜗牛在制定今天的旅游计划&#xff0c;有 n 个景点可选&#xff0c;它已经把这些景点按照顺路游览的顺序排 成一排了&#xff0c;每个地方有相应的景观&#xff0c;这里用一个整数表示。 蜗牛希望选取连续的一段景点&#xff0c;还要选出来的每一个景点的景观都不同…

ASP.NET Core基础 - 简介

目录 一. 简介 A、跨平台性 B、高性能 C、开源性 D、模块化与可扩展性 E、集成现代前端技术 二. ASP.NET 4.x 和 ASP.NET Core 比较 A、架构与平台支持 B、性能 C、开发体验 D、社区支持与生态系统 三. NET 与 .NET Framework 比较 A、概念范围 B、跨平台能力 C…

文献综述如何有助于识别研究中的关键变量和概念

VersaBot文献综述助手 进行良好的文献综述对于从多个方面确定研究的关键变量和概念起着至关重要的作用&#xff1b; 1.揭示相关领域和理论&#xff1a; 通过沉浸在现有的学术研究中&#xff0c;你会遇到围绕你的主题的各种理论和概念。这些可以作为识别与您的研究问题相关的潜…

天和环保业绩波动性明显,应收账款逾期率和回款率欠佳

《港湾商业观察》施子夫 7月17日&#xff0c;北交所网站更新唐山天和环保科技股份有限公司&#xff08;以下简称&#xff0c;天和环保&#xff09;及保荐机构江海证券关于第三轮审核问询函的回复。 公开信息显示&#xff0c;2023年6月&#xff0c;天和环保的IPO申请获受理。今…

Linux IPC解析:匿名命名管道与共享内存

目录 一.IPC机制介绍二.匿名与命名管道1.匿名管道2.命名管道3.日志 三.共享内存三.System V 标准1.System V简介2.IPC在内核的数据结构设计3.信号量 一.IPC机制介绍 IPC&#xff08;Inter-Process Communication&#xff0c;进程间通信&#xff09;是计算机系统中不同进程之间交…

还没用过OBS Studio?快来提升你的技术分享效率!

前言 在浩瀚的数字海洋中&#xff0c;有这么一款神器&#xff0c;它低调却光芒四射&#xff0c;默默改变着无数内容创作者的命运&#xff1b;嘿&#xff0c;你猜怎么着&#xff1f;它既不是天价的专业设备&#xff0c;也不是遥不可及的神秘黑科技&#xff0c;而是开源世界的瑰宝…

低功耗工业控制器用于风电场绿色可持续能源行业

全球对清洁能源的需求不断增长&#xff0c;风电场作为一种可再生能源的重要来源&#xff0c;正经历着快速发展。然而&#xff0c;传统的风电场管理和运营方式存在着效率低下、维护成本高等问题。为了提高风电场的运行效率和可靠性&#xff0c;实现绿色能源的可持续发展&#xf…

c语言-链表1

10 链表 一、链表是什么&#xff1f; -- 数据的一种存储方式 -- 链式存储 &#xff08;1&#xff09;线性存储 -- 地址连续 -- 自动开辟&#xff0c;自动释放 -- 默认是线性存储 &#xff08;2&#xff09;链式存储 -- 地址不连续…

【Git】git 从入门到实战系列(二)—— Git 介绍以及安装方法

文章目录 一、前言二、git 是什么三、版本控制系统是什么四、本地 vs 集中式 vs 分布式本地版本控制系统集中式版本控制系统分布式版本控制系统 五、安装 git 一、前言 本系列上一篇文章【Git】git 从入门到实战系列&#xff08;一&#xff09;—— Git 的诞生&#xff0c;Lin…

S硅谷-AI大模型实战训练

课程概述 AI大模型实战训练课程是一门专为有志于深入学习人工智能领域的学员设计的高级课程。本课程以当前人工智能领域的前沿技术——大模型为核心&#xff0c;通过理论与实践相结合的教学方式&#xff0c;培养学员在AI领域的实战能力。 课程目标 理解大模型的基本原理和架构。…

python爬虫之用scrapy下载中间件爬取网易新闻

python爬虫之用scrapy下载中间件爬取网易新闻 相关资源如下&#xff1a; 采用scrapy下载中间件爬取网易新闻国内、国际、数读、军事、航空五大板块新闻标题和内容 程序wangyi.py主代码&#xff1a; import scrapy from selenium import webdriver from selenium.webdriver.e…

PDF——分割pdf的10个工具

PDF分割器是一种可用于将PDF文档分割成更小的文档甚至单个页面的工具。分割 PDF 文档的主要原因是为了更容易共享。 但该过程的成功取决于您用于拆分 PDF 的工具。较简单的工具仅提供几个选项&#xff0c;可能并不适合所有类型的文档。我们将在本文中列出的 10 个最佳 PDF 分割…