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

设计模式二十二:策略模式(Strategy Pattern)

定义一系列算法,将每个算法封装成独立的对象,并使这些对象可互相替换。这使得在运行时可以动态地选择算法,而不必改变使用算法的客户端代码。策略模式的主要目标是将算法的定义与使用分离,使得客户端可以根据需要灵活地选择和切换不同的算法,而不影响到客户端代码的稳定性。

策略模式的使用场景

  1. 多种算法实现:
    当一个问题有多种算法实现时,可以使用策略模式来将这些算法封装成独立的策略类,使得这些算法可以互相替换,而不影响客户端代码。
  2. 避免条件判断:
    当存在大量的条件语句来选择不同的行为时,可以使用策略模式将这些行为封装成策略类,从而减少条件判断,提高代码的可读性和可维护性。
  3. 算法变化频繁:
    如果系统中的算法经常需要变化,使用策略模式可以方便地新增、修改和替换算法,而不必修改客户端代码。
  4. 开闭原则支持:
    策略模式支持开闭原则,可以在不修改已有代码的情况下扩展系统功能。
  5. 分层架构:
    在分层架构中,策略模式可以用于将业务逻辑与具体的实现分离,使得业务逻辑层和具体实现层解耦。
  6. 配置灵活性:
    当需要根据配置文件或用户输入来选择不同的行为时,策略模式可以提供灵活的配置方式。
  7. 测试和维护性:
    由于策略模式将不同的算法分离成独立的策略类,可以更方便地进行单元测试和维护。

策略模式主要角色

  1. 策略接口
    定义了一组算法的共同接口,具体策略类需要实现这个接口。它通常包含一个或多个抽象方法,用于定义不同算法的行为。
  2. 具体策略类
    实现了策略接口,即具体的算法逻辑。每个具体策略类负责实现一个特定的算法。具体策略类之间是可以相互替换的,客户端代码不需要知道具体算法的实现细节。
  3. 上下文
    持有一个策略对象,并在需要时调用策略的方法。上下文将算法的执行委托给具体的策略对象。上下文也可以包含一些辅助方法,用于操作策略对象。

策略模式的流程

  1. 客户端创建一个上下文对象,并设置具体的策略对象。
  2. 当客户端需要执行特定算法时,它调用上下文的方法,上下文会将请求委托给具体策略对象
  3. 具体策略对象执行算法,并将结果返回给上下文,上下文将结果传递给客户端。

策略模式java代码示例

实现一生鲜市场到点打折活动
策略接口

// 策略接口
public interface DiscountStrategy {double applyDiscount(double originalPrice);
}

策略实现类

public class RegularDiscount implements DiscountStrategy{@Overridepublic double applyDiscount(double originalPrice) {return originalPrice;//原价}
}public class SaleDiscount implements DiscountStrategy {@Overridepublic double applyDiscount(double originalPrice) {return originalPrice*0.8;//8折}
}public class SpecialDiscount  implements DiscountStrategy{@Overridepublic double applyDiscount(double originalPrice) {return originalPrice*0.5;//5折}
}

上下文

// 上下文类
public class ShoppingCart{private DiscountStrategy discountStrategy;public void setDiscountStrategy(DiscountStrategy discountStrategy) {this.discountStrategy = discountStrategy;}//获取最新价格public double getPrice(double regularPrice){return discountStrategy.applyDiscount(regularPrice);}}

客户端

public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();double originalPrice = 100.0;double discountedPrice;cart.setDiscountStrategy(new RegularDiscount());discountedPrice = cart.getPrice(originalPrice);System.out.println("8点价格:"+discountedPrice);cart.setDiscountStrategy(new SaleDiscount());discountedPrice = cart.getPrice(originalPrice);System.out.println("9点价格:"+discountedPrice);cart.setDiscountStrategy(new SpecialDiscount());discountedPrice = cart.getPrice(originalPrice);System.out.println("10点价格:"+discountedPrice);
}

输出

8点价格:100.0
9点价格:80.0
10点价格:50.0

策略模式优缺点

优点:

  1. 灵活性高: 策略模式使得算法可以独立地变化,而不会影响到客户端代码。可以随时切换或扩展算法,而无需修改客户端。
  2. 可维护性好: 每个具体策略类都具备清晰的职责,使得代码更加模块化和可读。新增或修改算法时,只需修改相应的策略类,不影响其他部分
  3. 遵循开闭原则: 策略模式支持开闭原则,可以在不修改已有代码的情况下添加新的策略类
  4. 消除条件判断: 策略模式可以避免大量的条件判断,将不同的行为封装到不同的策略类中,使得代码更加简洁
  5. 可测试性强: 每个策略类都是相对独立的,易于进行单元测试。

缺点:

  1. 类数量增多: 策略模式会引入多个具体策略类,可能导致类的数量增多,增加了代码的复杂度。
  2. 客户端需要了解策略: 客户端需要了解不同的策略类,并选择适当的策略,这可能在某些情况下增加了客户端的复杂度
  3. 增加对象数量: 每个策略类都是一个对象,可能会增加系统的对象数量。在某些情况下,可以通过共享策略对象来缓解这个问题
  4. 上下文类复杂: 上下文类需要持有一个策略对象,并在运行时选择合适的策略。在某些情况下,可能会使上下文类变得复杂

相关文章:

设计模式二十二:策略模式(Strategy Pattern)

定义一系列算法,将每个算法封装成独立的对象,并使这些对象可互相替换。这使得在运行时可以动态地选择算法,而不必改变使用算法的客户端代码。策略模式的主要目标是将算法的定义与使用分离,使得客户端可以根据需要灵活地选择和切换…...

【c语言】结构体内存对齐,位段,枚举,联合

之前学完结构体,有没有对结构体的大小会很疑惑呢??其实结构体在内存中存储时会存在内存对齐,捎带讲讲位段,枚举,和联合,跟着小张一起学习吧 结构体内存对齐 结构体的对齐规则: 第一个成员在与结…...

干货丨软件测试行业迎来新时代,AI将成为主流技术?

随着科技日新月异的发展,人工智能正逐渐渗透到我们生活的各方各面,从智能语音助手到自动驾驶汽车、从智能家居到人脸识别技术,AI正以其卓越的智能和学习能力引领着新时代的发展方向。 在这个快速演进的时代中,软件测试领域也受到了…...

MacOS goland go1.21 debug问题

安装dlv brew install dlv 安装之后在终端会显示所在目录 类似/usr/local/Cellar/delve/1.21.0/bin 配置goland 在文件系统中找到goland 右击选择show package contents -> Contents -> plugins -> go 尝试替换 其中对应系统 的 dlv 结果还是不行 然后打开应用gol…...

python 笔记(1)——基础和常用部分

目录 1、print 输出不换行 2、格式化输出字符串 3、浮点数的处理 4、进制转换和ASCII与字符间的转换 5、随机数 6、字符串截取和内置方法 6-1)字符串截取 6-2)字符串内置方法 7、元组、列表,及其遍历方式 7-1)列表常用内…...

kafka架构和原理详解

Apache Kafka 是一个分布式流数据平台,用于高吞吐量、持久性、可扩展的发布和订阅消息。它具有高度的可靠性,被广泛用于构建实时数据流处理、日志收集和数据管道等应用。 基本架构 1. 主题(Topic): 主题是消息的逻辑分类生产者将消息发布到特定的主题中,而消费者可以订阅…...

wsl Ubuntu中非root的普通用户怎么直接执行docker命令

docker需要root权限,如果希望非root用户直接使用docker命令,而不是使用sudo,可以选择将该用户加入到docker用户组。 sudo groupadd docker:添加到groupadd用户组(已经有docker用户组,所以可以不用再新增do…...

Web开发模式、API接口、restful规范、序列化和反序列化、drf安装和快速使用、路由转换器(复习)

一 Web开发模式 1. 前后端混合开发模式 前后端混合开发模式是一种开发方式,将前端和后端的开发工作结合在一起,以加快项目的开发速度和 提高协作效率。这种模式通常用于快速原型开发、小型项目或敏捷开发中。在前后端混合开发模式中,前端和…...

<AMBA总线篇> AXI总线协议介绍

目录 01 AXI协议简介 AXI协议特性 AXI协议传输特性 02 AXI协议架构 AXI协议架构 write transaction(写传输) read tramsaction(读传输) Interface and interconnect 典型的AXI系统拓扑 03 文章总结 大家好,这里是程序员杰克。一名平平无奇的嵌入式软件工程…...

一个简单的Python网络爬虫教程

网络爬虫是一种自动获取网页内容的程序,它可以从互联网上的网站中提取数据并进行分析。本教程将带您逐步了解如何使用 Python 构建一个简单的网络爬虫。 注意:在进行网络爬虫时,请遵守网站的使用条款和法律法规,避免对目标网站造…...

YARN资源管理框架论述

一、简介 为了实现一个Hadoop集群的集群共享、可伸缩性和可靠性,并消除早期MapReduce框架中的JobTracker性能瓶颈,开源社区引入了统一的资源管理框架YARN。 YARN是将JobTracker的两个主要功能(资源管理和作业调度/监控)分离&…...

Unity查找资源依赖关系

这个方法主要是发现资源乱用的情况,对应的逻辑可能要改一个才能用到自己的项目里面 [MenuItem("Tools/Prefab/查找选中资源依赖关系", false, 0)] public static void FindDependencies() { foreach (var guid in Selection.assetGUIDs…...

【操作系统】聊聊局部性原理是如何提升性能的

对于目前数据主导的系统,大多数都是Java/Go 技术栈MySQL,但是随着时间的推移,数据库数据的数据量过多,并且会频繁访问热点数据,为了提升系统的性能,一般都是加入缓存中间件、Redis。 局部性原理 我们知道…...

多线程应用——单例模式

单例模式 文章目录 单例模式一.什么是单例模式二.如何实现1.口头实现2.利用语法特性 三.实现方式(饿汉式懒汉式)1.饿汉式2.懒汉式3.线程安全的单例模式4.双重检查锁5.禁止指令重排序 一.什么是单例模式 单例模式(Singleton Pattern&#xff…...

几种在JavaScript中创建对象的方式!

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 字面量方式⭐ 构造函数方式⭐ Object.create()方式⭐ 工厂函数方式⭐ ES6类方式⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门…...

java项目mysql转postgresql

特殊函数 : mysql: find_in_set(?, ancestors) postgresql: ? ANY (string_to_array(ancestors,,)) mysql: date_format(t1.oper_time, %Y-%m-%d) postgresql: rksj::date to_char(inDate,YYYY-MM-DD) mysql&am…...

SpringBoot Mybatis 多数据源 MySQL+Oracle

一、背景 在SpringBoot Mybatis 项目中&#xff0c;需要连接 多个数据源&#xff0c;连接多个数据库&#xff0c;需要连接一个MySQL数据库和一个Oracle数据库 二、依赖 pom.xml <dependencies><dependency><groupId>org.springframework.boot</groupId&…...

(笔记五)利用opencv进行图像几何转换

参考网站&#xff1a;https://docs.opencv.org/4.1.1/da/d6e/tutorial_py_geometric_transformations.html &#xff08;1&#xff09;读取原始图像和标记图像 import cv2 as cv import numpy as np from matplotlib import pyplot as pltpath r"D:\data\flower.jpg&qu…...

【Flutter】Flutter 使用 fluttertoast 实现显示 Toast 消息

【Flutter】Flutter 使用 fluttertoast 实现显示 Toast 消息 文章目录 一、前言二、安装和基础使用三、不同平台的支持情况四、如何自定义 Toast五、在实际业务中的应用六、完整的业务代码示例&#xff08;基于 Web 端&#xff09;七、总结 一、前言 在这篇文章中&#xff0c;…...

nowcoder NC236题 最大差值

目录 题目描述&#xff1a; 示例1 示例2 题干解析&#xff1a; 暴力求解&#xff1a; 代码展示&#xff1a; 优化&#xff1a; 代码展示&#xff1a; 题目跳转https://www.nowcoder.com/practice/a01abbdc52ba4d5f8777fb5dae91b204?tpId128&tqId33768&ru/exa…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天&#xff0c;今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案&#xff0c;它们不仅提供了优雅的设计思路&#xff0c;还能显著提升系统的性能…...