行为型设计模式之策略模式【设计模式系列】

news2024/11/25 1:52:39

系列文章目录

C++技能系列
Linux通信架构系列
C++高性能优化编程系列
深入理解软件架构设计系列
高级C++并发线程编程
设计模式系列

期待你的关注哦!!!
在这里插入图片描述

现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。
Now everything is for the future of dream weaving wings, let the dream fly in reality.

行为型设计模式之策略模式

  • 系列文章目录
  • 一、策略模式介绍
  • 二、策略模式优缺点
    • 2.1 优点
    • 2.2 缺点
  • 三、策略模式使用场景
  • 四、策略模式实现

一、策略模式介绍

⚠️ 意图:
定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

⚠️ 主要解决:
在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。

⚠️ 何时使用:
一个系统有许多许多类,而区分它们的只是他们直接的行为。

⚠️ 如何解决:
将这些算法封装成一个一个的类,任意地替换。

在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

在这里插入图片描述

图1_1 策略模式类图

二、策略模式优缺点

2.1 优点

1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

2.2 缺点

1、策略类会增多。 2、所有策略类都需要对外暴露。

三、策略模式使用场景

1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

四、策略模式实现

ReplaceAlgorithm是一个抽象类,定义了算法的接口,有三个类继承自这个抽象类,也就是具体的算法实现。Cache类中需要使用替换算法,因此维护了一个 ReplaceAlgorithm的对象。

首先给出替换算法的定义。

//抽象接口
class ReplaceAlgorithm
{
public:
	virtual void Replace() = 0;
};
//三种具体的替换算法
class LRU_ReplaceAlgorithm : public ReplaceAlgorithm
{
public:
	void Replace() { cout<<"Least Recently Used replace algorithm"<<endl; }
};
 
class FIFO_ReplaceAlgorithm : public ReplaceAlgorithm
{
public:
	void Replace() { cout<<"First in First out replace algorithm"<<endl; }
};
class Random_ReplaceAlgorithm: public ReplaceAlgorithm
{
public:
	void Replace() { cout<<"Random replace algorithm"<<endl; }
};

接着给出Cache的定义,这里很关键,Cache的实现方式直接影响了客户的使用方式,其关键在于如何指定替换算法。

方式一:直接通过参数指定,传入一个特定算法的指针。

//Cache需要用到替换算法
class Cache
{
private:
	ReplaceAlgorithm *m_ra;
public:
	Cache(ReplaceAlgorithm *ra) { m_ra = ra; }
	~Cache() { delete m_ra; }
	void Replace() { m_ra->Replace(); }
};

如果用这种方式,客户就需要知道这些算法的具体定义。只能以下面这种方式使用,可以看到暴露了太多的细节。

int main()
{
	Cache cache(new LRU_ReplaceAlgorithm()); //暴露了算法的定义
	cache.Replace();
	return 0;
}

方式二:也是直接通过参数指定,只不过不是传入指针,而是一个标签。这样客户只要知道算法的相应标签即可,而不需要知道算法的具体定义。

//Cache需要用到替换算法
enum RA {LRU, FIFO, RANDOM}; //标签
class Cache
{
private:
	ReplaceAlgorithm *m_ra;
public:
	Cache(enum RA ra) 
	{ 
		if(ra == LRU)
			m_ra = new LRU_ReplaceAlgorithm();
		else if(ra == FIFO)
			m_ra = new FIFO_ReplaceAlgorithm();
		else if(ra == RANDOM)
			m_ra = new Random_ReplaceAlgorithm();
		else 
			m_ra = NULL;
	}
	~Cache() { delete m_ra; }
	void Replace() { m_ra->Replace(); }
};

相比方式一,这种方式用起来方便多了。其实这种方式将简单工厂模式与策略模式结合在一起,算法的定义使用了策略模式,而Cache的定义其实使用了简单工厂模式。

int main()
{
	Cache cache(LRU); //指定标签即可
	cache.Replace();
	return 0;
}

上面两种方式,构造函数都需要形参。构造函数是否可以不用参数呢?下面给出第三种实现方式。

方式三:利用模板实现。算法通过模板的实参指定。当然了,还是使用了参数,只不过不是构造函数的参数。在策略模式中,参数的传递难以避免,客户必须指定某种算法。

//Cache需要用到替换算法
template <class RA>
class Cache
{
private:
	RA m_ra;
public:
	Cache() { }
	~Cache() { }
	void Replace() { m_ra.Replace(); }
};

使用方式如下:

int main()
{
	Cache<Random_ReplaceAlgorithm> cache; //模板实参
	cache.Replace();
	return 0;
}

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

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

相关文章

OpenCV实现高斯模糊加水印

# coding:utf-8 # Email: wangguisendonews.com # Time: 2023/4/21 10:07 # File: utils.pyimport cv2 import PIL from PIL import Image import numpy as np from watermarker.marker import add_mark, im_add_mark import matplotlib.pyplot as plt# PIL Image转换成OpenCV格…

Docker 全栈体系(六)

Docker 体系&#xff08;高级篇&#xff09; 三、Docker微服务实战 1. 通过IDEA新建一个普通微服务模块 建Module docker_boot 改POM <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" …

【C#】医学实验室云LIS检验信息系统源码 采用B/S架构

基于B/S架构的医学实验室云LIS检验信息系统&#xff0c;整个系统的运行基于WEB层面&#xff0c;只需要在对应的工作台安装一个浏览器软件有外网即可访问&#xff0c;技术架构&#xff1a;Asp.NET CORE 3.1 MVC SQLserver Redis等。 一、系统概况 本系统是将各种生化、免疫、…

当ChatGPT应用在汽车行业,具体有哪些场景?

​ ChatGPT有潜力彻底改变汽车行业并将其提升到新的高度。在ChatGPT的加持下&#xff0c;该行业的多个领域都将取得重大变化。 利用ChatGPT作更高级的虚拟助理 你可能用过现有的虚拟助理&#xff0c;它们一系列的回复有时候让人不得不感叹一句“人工智障”&#xff01;然而&a…

【12】STM32·HAL库开发-STM32时钟系统 | F1/F4/F7时钟树 | 配置系统时钟

目录 1.认识时钟树&#xff08;掌握&#xff09;1.1什么是时钟&#xff1f;1.2认识时钟树&#xff08;F1&#xff09;1.2.1STM32F103时钟树简图1.2.2STM32CubeMX时钟树&#xff08;F103&#xff09; 1.3认识时钟树&#xff08;F4&#xff09;1.3.1F407时钟树1.3.2F429时钟树1.3…

【C++】解决菱形继承而产生的虚基表(偏移量表)

文章目录 继承概念切片和重定义派生类的默认成员函数菱形虚拟继承 继承概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派…

LeetCode91.Decode-Ways<解码方法>

题目&#xff1a; 思路&#xff1a; 关键在于有没有0,其次能不能二位.二位的要求是在 1-- 26的范围内.所以动态规划的时候需要限制. 代码是&#xff1a; //codeclass Solution { public:int numDecodings(string s) {int n s.size();vector<int> dp(n1, 0); // 定义状…

java使用htmlunit + jsoup 爬网站图片案例(爬虫学习)

申明 该文章用于自己学习爬虫使用 案例分析 目的: 从百度图片中搜索"风景"并下载图片到本地 思路: 使用htmlunit进行模拟用户操作, 并使用jsoup对数据进行解析,获取到需要的数据后,再下载到本地保存 htmlunit官网 jsoup官网 操作步骤 使用谷歌浏览器打开百度图片…

用html+javascript打造公文一键排版系统8:附件及标题排版

最近工作有点忙&#xff0c;所 以没能及时完善公文一键排版系统&#xff0c;现在只好熬夜更新一下。 有时公文有包括附件&#xff0c;招照公文排版规范&#xff1a; 附件应当另面编排&#xff0c;并在版记之前&#xff0c;与公文正文一起装订。“附件”二字及附件顺序号用3号黑…

Mysql适用于初学者的前期入门资料

文章目录 前言一、SQL语句分类二、SQL语句的书写规范三.数据库操作四、MySQL字符集1、问题① 五、UTF8和UTF8MB4的区别六、数据库对象七、数据类型八、表的基本创建1、创建表2、查看表3、删除表4、修改表结构5、复制表的结构 九、数据库字典十、表的约束1、非空约束(NOT NULL)2…

matplotlib从起点出发(4)_Tutorial_4_Lifecycle

1 一幅图像的生命周期 本教程旨在揭示使用matplotlib绘制的一幅图像的生命周期&#xff0c;包括它的开始、中间和结束。我们将从一些原始数据开始&#xff0c;最后保存自定义可视化的图形。在此过程中&#xff0c;我们尝试使用matplotlib突出一些简洁的功能和最佳实践。 2 关…

【Matlab】基于粒子群优化算法优化BP神经网络的时间序列预测(Excel可直接替换数据)

【Matlab】基于粒子群优化算法优化BP神经网络的时间序列预测&#xff08;Excel可直接替换数据&#xff09; 1.模型原理2.数学公式3.文件结构4.Excel数据5.分块代码5.1 fun.m5.2 main.m 6.完整代码6.1 fun.m6.2 main.m 7.运行结果 1.模型原理 基于粒子群优化算法&#xff08;Pa…

【LeetCode 75】第九题(443)压缩字符串

目录 题目: 示例: 分析: 题目: 示例: 分析: 给一个字符串,如果该字符有连续的相同的字符,则只保留一个字符,并在该字符后加上该字符连续的数量.例如原数组为 [a,a,a],则因为字符a连续了三次,因此可以压缩为[a,3],我们需要注意的是数字也需要是字符,则如果字符连续次数不止有…

SpringCloud学习路线(13)——分布式搜索ElasticSeach集群

前言 单机ES做数据存储&#xff0c;必然面临两个问题&#xff1a;海量数据的存储&#xff0c;单点故障。 如何解决这两个问题&#xff1f; 海量数据的存储问题&#xff1a; 将索引库从逻辑上拆分为N个分片&#xff08;shard&#xff09;&#xff0c;存储到多个节点。单点故障…

C++笔记之memset分析

C笔记之memset分析 code review! 文章目录 C\笔记之memset分析1.介绍2.误区总结3.代码一&#xff0c;char数组和uint8_t使用memset4.代码三&#xff0c;int数组使用memset 1.介绍 2.误区总结 参考文章&#xff1a;Cmemset踩坑 3.代码一&#xff0c;char数组和uint8_t使用mem…

2023年河北省研究生数学建模竞赛D题中国钢铁工业低碳转型与高质量发展路径优化研究思路和代码

D题中国钢铁工业低碳转型与高质量发展路径优化研究 目前已写出D题初步代码&#xff0c;下载地址&#xff1a;【2023年河北省研究生数学建模竞赛D题初步思路和代码-哔哩哔哩】 https://b23.tv/g2ATbX5 随着我国工业化、城镇化进程的加快和消费结构持续升级&#xff0c;能源需求…

tty(五)串口的打开过程

一、字符设备完成注册 我们知道&#xff0c;在serial核心层提供了2个重要接口 uart_register_driver uart_add_one_port 上者通过调用tty核心的接口&#xff0c;完成了tty_driver的动态分配和注册&#xff0c;然而此时并没有看到创建字符设备&#xff0c; 通过对uart_add_one…

货拉拉基于 Flink 计算引擎的应用与优化实践

摘要&#xff1a;本文整理自货拉拉实时研发平台负责人王世涛&#xff0c;在Flink Forward Asia 2022 平台建设专场的分享。本篇内容主要分为六个部分&#xff1a; Flink 在货拉拉的使用现状Flink 平台化性能优化主题数据准确性主题稳定性主题未来展望 点击查看原文视频 & 演…

【leetcode】链表的中间节点|链表中倒数第k个节点

目录 1.链表的中间节点 2.链表中倒数第k个节点 1.链表的中间节点 思路1&#xff1a;遍历链表&#xff0c;统计节点个数count&#xff0c;返回第count/2 1个节点 &#x1f4d6;Note:注意循环条件为--mid&#xff0c;--mid循环执行mid-1次&#xff0c;mid--循环mid次&#xf…

SpringBoot 8种异步实现方式

前言&#xff1a;异步执行对于开发者来说并不陌生&#xff0c;在实际的开发过程中&#xff0c;很多场景多会使用到异步&#xff0c;相比同步执行&#xff0c;异步可以大大缩短请求链路耗时时间&#xff0c;比如&#xff1a;「发送短信、邮件、异步更新等」&#xff0c;这些都是…