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

Gof23设计模式之策略模式

1.概述

该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

2.结构

策略模式的主要角色如下:

  • 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。
  • 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

3.案例

/*** @author 晓风残月Lx* @date 2023/7/26 19:56*      抽象策略类*/
public interface Strategy {void show();
}
/*** @author 晓风残月Lx* @date 2023/7/26 19:59*      具体策略类*/
public class StrategyA implements Strategy{@Overridepublic void show() {System.out.println("策略1");}
}/*** @author 晓风残月Lx* @date 2023/7/26 19:59*      具体策略类*/
public class StrategyB implements Strategy{@Overridepublic void show() {System.out.println("策略2");}
}/*** @author 晓风残月Lx* @date 2023/7/26 19:59*      具体策略类*/
public class StrategyC implements Strategy{@Overridepublic void show() {System.out.println("策略3");}
}
/*** @author 晓风残月Lx* @date 2023/7/26 20:00*      促销员(环境类)*/
public class SalesMan {// 聚合策略类对象private Strategy strategy;public Strategy getStrategy() {return strategy;}public void setStrategy(Strategy strategy) {this.strategy = strategy;}public SalesMan(Strategy strategy) {this.strategy = strategy;}// 由促销员展示促销活动给用户public void salesManShow() {strategy.show();}}
/*** @author 晓风残月Lx* @date 2023/7/26 20:02*/
public class Client {public static void main(String[] args) {SalesMan salesMan = new SalesMan(new StrategyA());salesMan.salesManShow();salesMan.setStrategy(new StrategyC());salesMan.salesManShow();}
}

在这里插入图片描述

4.优缺点

1,优点:

  • 策略类之间可以自由切换

    由于策略类都实现同一个接口,所以使它们之间可以自由切换。

  • 易于扩展

    增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“

  • 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。

2,缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
  • 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。

5.使用场景

  • 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。
  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。
  • 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。
  • 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。
  • 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。

6.JDK源码解析

Comparator 中的策略模式。在Arrays类中有一个 sort() 方法,如下:

public class Arrays{public static <T> void sort(T[] a, Comparator<? super T> c) {if (c == null) {sort(a);} else {if (LegacyMergeSort.userRequested)legacyMergeSort(a, c);elseTimSort.sort(a, 0, a.length, c, null, 0, 0);}}
}

Arrays就是一个环境角色类,这个sort方法可以传一个新策略让Arrays根据这个策略来进行排序。就比如下面的测试类。

public class demo {public static void main(String[] args) {Integer[] data = {12, 2, 3, 2, 4, 5, 1};// 实现降序排序Arrays.sort(data, new Comparator<Integer>() {public int compare(Integer o1, Integer o2) {return o2 - o1;}});System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1]}
}

这里我们在调用Arrays的sort方法时,第二个参数传递的是Comparator接口的子实现类对象。所以Comparator充当的是抽象策略角色,而具体的子实现类充当的是具体策略角色。环境角色类(Arrays)应该持有抽象策略的引用来调用。那么,Arrays类的sort方法到底有没有使用Comparator子实现类中的 compare() 方法吗?让我们继续查看TimSort类的 sort() 方法,代码如下:

class TimSort<T> {static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,T[] work, int workBase, int workLen) {assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;int nRemaining  = hi - lo;if (nRemaining < 2)return;  // Arrays of size 0 and 1 are always sorted// If array is small, do a "mini-TimSort" with no mergesif (nRemaining < MIN_MERGE) {int initRunLen = countRunAndMakeAscending(a, lo, hi, c);binarySort(a, lo, hi, lo + initRunLen, c);return;}...}   private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,Comparator<? super T> c) {assert lo < hi;int runHi = lo + 1;if (runHi == hi)return 1;// Find end of run, and reverse range if descendingif (c.compare(a[runHi++], a[lo]) < 0) { // Descendingwhile (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)runHi++;reverseRange(a, lo, runHi);} else {                              // Ascendingwhile (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)runHi++;}return runHi - lo;}
}

上面的代码中最终会跑到 countRunAndMakeAscending() 这个方法中。我们可以看见,只用了compare方法,所以在调用Arrays.sort方法只传具体compare重写方法的类对象就行,这也是Comparator接口中必须要子类实现的一个方法。

相关文章:

Gof23设计模式之策略模式

1.概述 该模式定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以相互替换&#xff0c;且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式&#xff0c;它通过对算法进行封装&#xff0c;把使用算法的责任和算法的实现分割开来&#xff0c;…...

SAP 物料主数据屏幕增强

增强步骤 1.为主表添加一个附加结构 根据业务需求新建一个结构&#xff0c;结构中放入需要增强的屏幕字段并激活。 打开事务代码SE11&#xff0c;在需要保存的主表中添加这个附加结构并激活。 注&#xff1a;根据业务需求及屏幕增强的视图判断需要保存的主表是哪张&#xff…...

数据库-索引

介绍&#xff1a; 索引是帮助数据库高效获取数据的数据结构 优缺点&#xff1a; 优点&#xff1a;提高数据查询的效率&#xff0c;降低数据库的IO成本 通过索引列对数据进行排序&#xff0c;降低数据排序的成本&#xff0c;降低cpu消耗 缺点&#xff1a;索引会占用存储空间 索…...

Excel·VBA二维数组组合函数的应用实例

看到一个问题《关于#穷举#的问题&#xff0c;如何解决&#xff1f;(语言-开发语言)》&#xff0c;对同一个数据存在“是/否”2种状态&#xff0c;判断其是否参与计算&#xff0c;并输出一系列数据的“是/否”状态的结果 目录 方法1&#xff1a;二维数组组合函数结果 方法2&am…...

hive anti join 的几种写法

t_a 表的记录如下 c1 | :———— | a | b | c | 生成 SQL 如下&#xff1a; create table t_a(c1 string); insert into t_a values("a"),("b"),("c");t_b 表的记录如下 c1bm 生成 SQL 如下&#xff1a; create table t_b(c1 string); in…...

使用Android原生制作毛玻璃效果图片

毛玻璃效果&#xff0c;也被称为模糊效果&#xff0c;是许多现代应用中流行的一种视觉效果。在 Android 中&#xff0c;我们可以通过多种方式实现该效果。本文将探讨如何使用 Android 原生的 Bitmap 类和 RenderScript 来实现毛玻璃效果。 1. 准备工作 首先&#xff0c;你需要…...

软件设计的七大原则

一. 软件设计的七大原则 单一职责原则&#xff1a;一个类只负责一个功能领域中的饿相应职责。开闭原则&#xff1a;对扩展开放&#xff0c;对修改关闭&#xff0c;多使用抽象类和接口&#xff0c;应该尽量使这个系统能够扩展新的功能&#xff0c;通过扩展来实现变化&#xff0…...

Windows下安装配置Nginx

nginx安装 官网下载地址 https://nginx.org/en/download.html 推荐使用稳定版本 截止时间2023年9月5日稳定版本为 1.24.0 百度网盘 链接&#xff1a;https://pan.baidu.com/s/1cXm-jN2fMzKdVMRhbG72Fg 提取码&#xff1a;9hcq 下载完成以后,得到nginx压缩包; 双击启动nginx.…...

数据结构类型

1.在C和C中static关键字的用法 在C中 1.static修饰未初始化全局变量&#xff0c;默认结果为0 2.static修饰局部变量&#xff0c;延长生命周期&#xff0c;生命周期不是作用域&#xff0c;它依旧是局部变量 3.static修饰函数只能在当前文件中调用&#xff0c;不可用跨文件调用…...

WPF元素绑定

简单的说&#xff0c;数据绑定是一种关系&#xff0c;该关系告诉WPF从源对象提取一些信息&#xff0c;并用这些信息设置目标对象的属性。目标属性始终是依赖属性&#xff0c;通常位于WPF元素中——毕竟&#xff0c;WPF数据绑定的最终目标是在用户界面中显示一些信息。然而&…...

centos编译升级cmake,痛苦的Linux小白

环境 root 用户 下载 cmake官网下载地址&#xff1a;https://cmake.org/download/ 获取下载地址&#xff0c;右击cmake-3.27.4.tar.gz 命令行输入链接地址&#xff0c;下载 wget https://github.com/Kitware/CMake/releases/download/v3.27.4/cmake-3.27.4.tar.gz解压 tar -zx…...

Unity资源无法下载 反复提示需同意Terms of Service和EULA 同意后无效的解决方案

前言 最近在玩Unity&#xff0c;跟着tutorial做点项目&#xff0c;但是在下载免费资源时&#xff0c;只有从网站上点“打开Unity”&#xff0c;才能在本地Unity Editor的Package Manager里找到这个资源&#xff08;且点一下下面的刷新就没有了&#xff09;&#xff0c;并且点击…...

记录--vue 拉伸指令

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 在我们项目开发中,经常会有布局拉伸的需求,接下来 让我们一步步用 vue指令 实现这个需求 动手开发 在线体验 codesandbox.io/s/dawn-cdn-… 常规使用 解决拉伸触发时机 既然我们使用了指令的方式…...

前端缓存方法有哪些?cookie有哪些属性?

这里写目录标题 前端缓存方法有哪些&#xff1a;cookie有哪些属性&#xff1f; 前端缓存方法有哪些&#xff1a; Browser Cache&#xff08;浏览器缓存&#xff09;: 当浏览器请求一个资源&#xff08;例如图片、CSS、JS 文件&#xff09;时&#xff0c;它会首先检查自己的缓存…...

在PHP8中遍历数组-PHP8知识详解

所谓遍历数组就是把数组中的变量值读取出来。遍历数组中的所有元素对程序员来说是经常使用的操作&#xff0c;通过遍历数组可以完成数组元素的查询工作。 这好比你去商场买东西一样&#xff0c;要买什么东西&#xff0c;就去该区域浏览一遍&#xff0c;以便找出适合自己的产品…...

代码随想录算法训练营之JAVA|第四十三天|139. 单词拆分

今天是第 天刷leetcode&#xff0c;立个flag&#xff0c;打卡60天。 算法挑战链接 139. 单词拆分https://leetcode.cn/problems/word-break/ 第一想法 看完之后完全没有想法。 看完代码随想录之后的想法 这是一个完全背包的问题&#xff0c;使用完全背包的解法。 单词就…...

解决VUE3项目部署后存在缓存页面不更新的问题

方法一&#xff1a; 找到项目中的index.html文件&#xff0c;在头部加上以下代码 <meta http-equiv"Pragma" content"no-cache"> <meta http-equiv"Cache-control" content"no-cache"> <meta http-equiv"Cache&…...

私募证券基金动态-23年8月报

成交量&#xff1a;8月日均8,252.00亿元 8月A股两市日均成交8,252.00亿元&#xff0c;环比下降12.23%、同比下降18.11%。8月整体23个交易日&#xff0c;仅有3个交易日单日成交金额过万亿&#xff0c;且成交量起伏较大&#xff0c;单日成交金额最低仅有6805.32亿元&#xff08;…...

Qt/C++音视频开发49-推流到各种流媒体服务程序

一、前言 最近将推流程序完善了很多功能&#xff0c;尤其是增加了对多种流媒体服务程序的支持&#xff0c;目前支持mediamtx、LiveQing、EasyDarwin、nginx-rtmp、ZLMediaKit、srs、ABLMediaServer等&#xff0c;其中经过大量的对比测试&#xff0c;个人比较建议使用mediamtx和…...

深度学习学习笔记——解决过拟合问题的方法:权重衰减和暂退法,与正则化之间的关系

解决过拟合问题是机器学习和深度学习中关键的任务之一&#xff0c;因为它会导致模型在训练数据上表现良好&#xff0c;但在未见数据上表现不佳。以下是一些解决过拟合问题的常见方法&#xff1a; 增加训练数据&#xff1a; 增加更多的训练数据可以帮助模型更好地捕捉数据的真实…...

Boss直聘职位数据自动化采集:Python爬虫架构设计与工程实践

1. 项目概述与核心价值最近在技术社区里&#xff0c;看到不少朋友在讨论一个叫longsizhuo/BossZhiPin_Job_Search的项目。光看名字&#xff0c;你大概就能猜到&#xff0c;这是一个跟“Boss直聘”和“职位搜索”相关的自动化工具。作为一个在招聘数据分析和自动化领域摸爬滚打了…...

高效视频帧提取终极指南:为深度学习构建专业数据集

高效视频帧提取终极指南&#xff1a;为深度学习构建专业数据集 【免费下载链接】video2frame Yet another easy-to-use tool to extract frames from videos, for deep learning and computer vision. 项目地址: https://gitcode.com/gh_mirrors/vi/video2frame 在计算机…...

Steam成就管理器终极指南:3步修复错失的游戏成就

Steam成就管理器终极指南&#xff1a;3步修复错失的游戏成就 【免费下载链接】SteamAchievementManager A manager for game achievements in Steam. 项目地址: https://gitcode.com/gh_mirrors/st/SteamAchievementManager Steam Achievement Manager&#xff08;SAM&a…...

从零到联网:QNX Neutrino RTOS安装后的第一个网络配置实战(含ifconfig与DHCP详解)

从零到联网&#xff1a;QNX Neutrino RTOS安装后的第一个网络配置实战 当你第一次看到QNX Neutrino RTOS的Photon桌面时&#xff0c;那种兴奋感可能很快会被一个现实问题冲淡——这个看起来酷炫的系统怎么连上网&#xff1f;作为实时操作系统领域的标杆&#xff0c;QNX在车载系…...

基于Claude API构建AI代码生成工具:从API封装到工程化实践

1. 项目概述与核心价值最近在开发者社区里&#xff0c;一个名为ashish200729/claude-code-source-code的项目标题引起了不小的讨论。乍一看&#xff0c;这个标题很容易让人产生误解&#xff0c;以为这是某个知名AI模型的源代码被公开了。但作为一名在软件开发和开源领域摸爬滚打…...

Pixel Framebuf库:图形化编程驱动LED矩阵,告别底层坐标换算

1. 项目概述&#xff1a;告别点灯&#xff0c;拥抱图形化LED矩阵编程如果你玩过Arduino或者树莓派&#xff0c;大概率接触过WS2812B这类可寻址LED&#xff0c;也就是大家常说的NeoPixel。单个灯珠的控制很简单&#xff0c;setPixelColor一下就能亮。但当你面对一个8x8、16x16甚…...

EL电致发光线与3D打印技术打造可穿戴发光骨架服

1. 项目概述&#xff1a;当发光骨架“活”过来每年万圣节&#xff0c;看着满大街的“幽灵”和“僵尸”&#xff0c;我总想搞点不一样的。直到去年&#xff0c;我决定不再满足于商店里千篇一律的服装&#xff0c;而是想自己动手&#xff0c;做一件真正能“发光”的、有科技感的骨…...

FPGA与GPU在OSOS-ELM算法中的性能对比与优化

1. 项目概述在边缘计算和实时信号处理领域&#xff0c;极端学习机(ELM)因其独特的训练机制和高效的计算性能而备受关注。OSOS-ELM作为ELM的一种变体&#xff0c;通过在线顺序学习机制进一步提升了算法的实用性。这项研究聚焦于FPGA和GPU两种硬件平台在执行OSOS-ELM算法时的性能…...

AI智能体开发实战:从Devin现象到代码辅助智能体构建

1. 项目概述&#xff1a;当开发者遇上AI智能体最近在GitHub上闲逛&#xff0c;发现一个叫“awesome-devins”的仓库热度飙升。点进去一看&#xff0c;好家伙&#xff0c;这简直是一个关于“AI智能体”的宝藏目录。这个由e2b-dev团队维护的项目&#xff0c;本质上是一个精心整理…...

基于二维码的文件分片传输:原理、实现与安全应用

1. 项目概述&#xff1a;一个基于二维码的智能文件分发系统 最近在折腾一个挺有意思的小项目&#xff0c;源于一个很实际的需求&#xff1a;如何在不同的设备之间&#xff0c;安全、便捷地传输一些敏感或临时的文件&#xff0c;而不依赖任何第三方云存储或即时通讯工具。你可能…...