[设计模式Java实现附plantuml源码~行为型]算法的封装与切换——策略模式

前言:
为什么之前写过Golang 版的设计模式,还在重新写Java 版?
答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。
为什么类图要附上uml
因为很多人学习有做笔记的习惯,如果单纯的只是放一张图片,那么学习者也只能复制一张图片,可复用性较低,附上uml,方便有新理解时,快速出新图。


🔥[设计模式Java实现附plantuml源码]专链

  • 创建型
  1. 确保对象的唯一性~单例模式
  2. 集中式工厂的实现~简单工厂模式
  3. 多态工厂的实现——工厂方法模式
  4. 产品族的创建——抽象工厂模式
  5. 对象的克隆~原型模式
  6. 复杂对象的组装与创建——建造者模式
  • 结构型
  1. 提供统一入口——外观模式
  2. 扩展系统功能——装饰模式
  3. 树形结构的处理——组合模式
  4. 对象的间接访问——代理模式
  5. 不兼容结构的协调——适配器模式
  6. 处理多维度变化——桥接模式
  7. 实现对象的复用——享元模式
  • 行为型
  1. 请求的链式处理——职责链模式

  2. 请求发送者与接收者解耦——命令模式

  3. 遍历聚合对象中的元素——迭代器模式

  4. 协调多个对象之间的交互——中介者模式

  5. 对象间的联动~观察者模式

  6. 算法的封装与切换——策略模式


文章目录

      • 思考 一个环境类Context能否对应多个不同的策略等级结构?如何设计?
      • 简单代码实现
      • 简单总结
        • 主要优点
        • 主要缺点
      • 适用场景


在策略模式中,可以定义一些独立的类来封装不同的算法,每个类封装一种具体的算法。在这里,每个封装算法的类都可以称之为一种策略(Strategy)。为了保证这些策略在使用时具有一致性,一般会提供一个抽象的策略类来做规则的定义,而每种算法则对应于一个具体策略类。
策略模式的主要目的是将算法的定义与使用分开,也就是将算法的行为和环境分开。将算法的定义放在专门的策略类中,每个策略类封装了一种实现算法。使用算法的环境类针对抽象策略类进行编程,符合依赖倒转原则。在出现新的算法时,只需要增加一个新的实现了抽象策略类的具体策略类即可。

策略模式定义如下:
策略模式(Strategy Pattern):定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式。

策略模式结构并不复杂,但需要理解其中环境类Context的作用,其结构如图所示。
在这里插入图片描述

@startumlclass Context {
- strategy: Strategy
+ algorithm()
}
note left of Context::algorithm
strategy.algorithm()
end noteabstract Strategy {
+ algorithm()
}class ConcreteStrategyA extends Strategy {
+ algorithm()
}class ConcreteStrategyB extends Strategy {
+ algorithm()
}Context *-right-> Strategy: strategy@enduml

在策略模式结构图中包含以下3个角色。
(1)Context(环境类):环境类是使用算法的角色,它在解决某个问题(即实现某个方法)时可以采用多种策略。在环境类中维持一个对抽象策略类的引用实例,用于定义所采用的策略。
(2)Strategy(抽象策略类):它为所支持的算法声明了抽象方法,是所有策略类的父类。它可以是抽象类或具体类,也可以是接口。环境类通过抽象策略类中声明的方法在运行时调用具体策略类中实现的算法。
(3)ConcreteStrategy(具体策略类):它实现了在抽象策略类中声明的算法。在运行时,具体策略类将覆盖在环境类中定义的抽象策略类对象,使用一种具体的算法实现某个业务处理。

思考 一个环境类Context能否对应多个不同的策略等级结构?如何设计?

策略模式是一个比较容易理解和使用的设计模式。策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列具体策略类里面,作为抽象策略类的子类。
在策略模式中,对环境类和抽象策略类的理解非常重要,环境类是需要使用算法的类。在一个系统中可以存在多个环境类,它们可能需要重用一些相同的算法。在使用策略模式时,需要将算法从Context类中提取出来。

简单代码实现

package behavior;public class StrategyDemo {public static void main(String[] args) {Strategy strategy = new ConcreteStrategy();Context context = new Context(strategy);context.algorithm();}public static abstract class Strategy {public void algorithm() {System.out.println("算法");};}public static  class Context {private final Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public void algorithm(){strategy.algorithm();}}public static class ConcreteStrategy extends Strategy {@Overridepublic void algorithm() {System.out.println("策略A");}}
}

在客户端代码中只需注入一个具体策略对象。可以将具体策略类类名存储在配置文件中,通过反射来动态创建具体策略对象,从而使得用户可以灵活地更换具体策略类,增加新的具体策略类也很方便。策略模式提供了一种可插入式(Pluggable)算法的实现方案。

简单总结

策略模式用于算法的自由切换和扩展,它是应用较为广泛的设计模式之一。策略模式对应于解决某一问题的一个算法族,允许用户从该算法族中任选一个算法来解决某一问题,同时可以方便地更换算法或者增加新的算法。只要涉及算法的封装、复用和切换都可以考虑使用策略模式。

主要优点

策略模式的主要优点如下:
(1)策略模式提供了对开闭原则的完美支持。用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
(2)策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到抽象策略类中,从而避免重复代码。
(3)策略模式提供了一种可以替换继承关系的办法。如果不使用策略模式,那么使用算法的环境类就可能会有一些子类,每一个子类提供一种不同的算法。但是,这样一来算法的使用就和算法本身混在一起,不符合单一职责原则。决定使用哪一种算法的逻辑和该算法本身混合在一起,从而不可能再独立演化;而且使用继承无法实现算法或行为在程序运行时的动态切换。
(4)使用策略模式可以避免多重条件选择语句。多重条件选择语句不易维护,它把采取哪一种算法或行为的逻辑与算法或行为本身的实现逻辑混合在一起,将它们全部硬编码(Hard Coding)在一个庞大的多重条件选择语句中,比直接继承环境类的办法还要原始和落后。
(5)策略模式提供了一种算法的复用机制。由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便地复用这些策略类。

主要缺点

策略模式的主要缺点如下:
(1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
(2)策略模式将造成系统产生很多具体策略类。任何细小的变化都将导致系统要增加一个新的具体策略类。
(3)无法同时在客户端使用多个策略类。也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况。

适用场景

在以下情况下可以考虑使用策略模式:
(1)一个系统需要动态地在几种算法中选择一种。可以将这些算法封装到一个个的具体算法类中,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均具有统一的接口。根据里氏代换原则和面向对象的多态性,客户端可以选择使用任何一个具体算法类,并只需要维持一个数据类型是抽象算法类的对象。
(2)一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句。
(3)不希望客户端知道复杂的、与算法相关的数据结构。在具体策略类中封装算法与相关的数据结构,可以提高算法的保密性与安全性。



🚀 作者简介:作为某云服务提供商的后端开发人员,我将在这里与大家简要分享一些实用的开发小技巧。在我的职业生涯中积累了丰富的经验,希望能通过这个博客与大家交流、学习和成长。技术栈:Java、Golang、PHP、Python、Vue、React


本文收录于三木的
💐 「设计模式」专栏
此外三木还有以下专栏在同步更新~

🌼 「AI」专栏

🔥「面试」这个专栏的灵感来自于许多粉丝私信,大家向我咨询有关面试的问题和建议。我深感荣幸和责任,希望通过这个专栏,能够为大家提供更多关于面试的知识、技巧和经验。我们将一起探讨面试。期待粉丝们ssp的offer喜讯。

🎈 「Java探索者之路」系列专栏,这个专栏旨在引领Java开发者踏上一段真正探索Java世界的旅程。
我们将深入探讨Java编程的方方面面,从基础知识到高级技巧,从实践案例到最新趋势,帮助你成为一名卓越的Java探索者。如果有想进入Java后端领域工作的同学,这个专栏会对你有所帮助,欢迎关注起来呀

🌊 「Python爬虫」的入门学习系列,大家有兴趣的可以看一看


🌹一起学习,互三互访,顺评论区有访必回,有关必回!!!


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

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

相关文章

设计模式--总结和对比

设计模式原则 设计原则一句话归纳目的 开闭原则(OCP) (Open-Close) 对扩展开放,对修改关闭减少维护带来新的风险 依赖倒置原则(DIP) (Dependence Inversion) 高层不应该依赖底层更利于代码结构的升级 扩展 单一职责原则(SRP) (Simple Responsibility) 一个类只干一…

我的NPI项目之Android Camera (四)-- 对应Camera tuning的一些理解

Camera作为产品的一个核心部件,在产品竞争力方面有着不容争辩的地位。所以,选择一款合适的Camera模组并发挥出模组的性能对项目极其重要。 在Camera的选型方面,我不用多说,国内前五的有:舜宇,丘钛&#xff…

消息中间件相关介绍

一、消息中间件相关知识 1、概述 消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ&am…

【iOS ARKit】ARWorldMap

ARWorldMap 用于存储 ARSession 检测扫描到的空间信息数据,包括地标(Landmark)、特征点(Feature Point)、平面(Plane)等,以及使用者的操作信息,如使用者添加的 ARAnchor …

数据采集设备:安装过程的要点与注意事项

在当今的数据驱动世界,数据采集设备在各行各业中发挥着至关重要的作用。从工业生产到环境监测,再到医疗诊断,数据采集设备为我们提供了大量有价值的信息。然而,要想充分发挥这些设备的潜力,首先需要确保它们被正确地安…

黑马程序员——接口测试——day03

目录: Potman断言 Postman断言简介Postman常用断言 断言响应状态码断言包含某字符串断言JSON数据Postman断言工作原理Postman关联 简介实现步骤核心代码创建环境案例1案例2Postman参数化 简介数据文件简介编写数据文件 CSV文件JSON文件导入数据文件到postman读取数…

杂题——亲密数

题目描述 两个不同的自然数A和B,如果整数A的全部因子(包括1,不包括A本身)之和等于B;且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。求3000以内的全部亲密数。 输入格式 无 输出格式 3000以内…

【AHK】68键键盘键位布局优化/esc改退格键/回车键

本人习惯使用~作为退格键,但是由于keychron 68键的布局只能用esc平替~来修改,然后也将回车键通过alt和大小写锁定键一起触发 esc::bs ;次步骤与下面步骤相对应,如果是用send bs方式则下面的不生效^esc:: ;通过建立 保留esc功能 send {esc} re…

啊丢的刷题记录手册(洛谷题单排序篇)

1.洛谷题P1923 求第k小的数 题目描述 输入 n&#xff08;1≤n<5000000 且 n 为奇数&#xff09;个数字ai​&#xff08;1≤ai​<109&#xff09;&#xff0c;输出这些数字的第 k 小的数。最小的数是第 0 小。 请尽量不要使用 nth_element 来写本题&#xff0c;因为本题…

换档控制支架的尺寸优化

前言 本示例使用优化模块&#xff0c;通过在保持原始重量的同时改变壳体厚度&#xff0c;使冲压钣金支架中的应变能之和最小化&#xff08;使刚度最大化&#xff09;。 本页讨论 前言应用描述Abaqus建模方法和仿真技术文件参考 应用描述 本示例说明了汽车变速箱连杆中使用的…

亿道丨三防平板pad丨三防平板是指哪三防丨三防工业级平板电脑

三防工业级平板电脑成为许多行业中的重要工具。本文将介绍三防工业级平板电脑的特点以及其在各个领域中的广泛应用。 三防工业级平板电脑的特点 三防工业级平板电脑是指具备防水、防尘和防震功能的平板电脑。这些特点使得它们能够在恶劣环境中工作&#xff0c;如沙尘飞扬的工地…

sockaddr结构体、sockaddr_in结构体和gethostbyname函数

sockaddr结构体 sockaddr结构体是在网络编程中经常使用的一个数据结构&#xff0c;用来表示套接字地址。它是一个通用的地址结构&#xff0c;可以用于不同的协议&#xff08;如IPv4、IPv6、UNIX等&#xff09;。 在C语言中&#xff0c;sockaddr结构体定义如下&#xff1a; s…

交换两个整数

交换两个整数 题目描述&#xff1a;解法思路&#xff1a;解法代码&#xff1a;运行结果&#xff1a; 题目描述&#xff1a; 写⼀个函数Swap&#xff0c;可以交换两个整数的内容。注意必须实现成函数完成。 输入2个整数&#xff0c;调用自定义函数Swap&#xff0c;完成2个整数的…

C++面试 -操作系统-代码能力:用户态和内核态的基本概念、区别

目录 一、基本概念 概念&#xff1a; 区别&#xff1a; 二、Windows示例 基础介绍 用户态到内核态的切换过程&#xff1a; 程序实例 三、Linux示例 特权级别&#xff1a; 用户态到内核态的切换过程&#xff1a; 调度和中断处理&#xff1a; 程序实例 总结 在操作系…

Java多线程面试题(三)

Java多线程面试题&#xff08;三&#xff09; 前言1、Thread 类中的 yield 方法有什么作用&#xff1f;2、Java 线程池中 submit() 和 execute()方法有什么区别&#xff1f;3、Java 中的 ReadWriteLock 是什么&#xff1f;4、可以直接调用 Thread 类的 run ()方法么&#xff1f…

【升级JDK21】遇到:服务配置文件不正确, 或构造处理程序对象

RROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile(default-compile) on project tr-public-opinion-collector-start: Compilation failure [ERROR] 服务配置文件不正确, 或构造处理程序对象javax.annotation.processing.Processor:…

【HarmonyOS】鸿蒙开发之Stage模型-基本概念——第4.1章

Stage模型-基本概念 名词解释 AbilityStage:应用组件的“舞台“ UIAbility:包含UI界面的应用组件&#xff0c;是系统调度的基本单元 WindowStage:组件内窗口的“舞台“ Window&#xff1a;用来绘制UI页面的窗口 HAP:Harmony Ability Package(鸿蒙能力类型的包) HSP:Harmony Sh…

C++17之折叠表达式

相关文章系列 深入理解可变参数(va_list、std::initializer_list和可变参数模版) 目录 1.介绍 2.应用 2.1.使用折叠表达式 2.2.支持的运算符 2.3.使用折叠处理类型 3.总结 1.介绍 折叠表达式是C17新引进的语法特性。使用折叠表达式可以简化对C11中引入的参数包的处理&…

合泰杯开发板HT66F2390入门教程(点亮LED灯)——获得成就:点灯大师

前言 前不久报名了合泰杯竞赛项目&#xff0c;然后手上也是有一个HT66F2390的开发板&#xff0c;我就打算先从点灯开始&#xff0c;学习一个新的芯片第一步都是先成为点灯大师。 一开始&#xff0c;我在网上搜寻了许多的代码示例&#xff0c;希望能够顺利实现LED的控制。然而&…

LeetCode第七题: 整数反转

题目描述 给你一个 32 位的有符号整数 x​ &#xff0c;返回将 x​ 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1]​ &#xff0c;就返回 0。 假设环境不允许存储 64 位整数&#xff08;有符号或无符号&#xff09;。 示例 …