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

2023-11-03

系列文章目录

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

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

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

一、策略模式介绍

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

⚠️ 主要解决:
在有多种算法相似的情况下,使用 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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

行为型设计模式之策略模式【设计模式系列】 的相关文章

  • 有没有办法使 C90 标准中的枚举无符号? (符合 MISRA-C 2004 标准)

    我正在尝试找到一种使枚举 无符号 的方法 enum x1 0 x2 x3 uint8 t x2 lt PC LINT MISRA C 2004 will complain about mixing signed and unsigned h
  • Entity Framework 4.1 RC:Code First EntityTypeConfiguration 继承问题

    我尝试使用通用的 EntityTypeConfiguration 类来配置所有实体的主键 以便每个派生的配置类不会重复自身 我的所有实体都实现一个公共接口 IEntity 它表示每个实体必须有一个 int 类型的 Id 属性 我的配置基类如
  • async wait 在调用异步方法时返回 Task> 而不是 List

    我正在尝试了解 async wait 的用法 并且研究了一些博客文章 现在我已经编写了一个测试代码 但它没有按照我期望的方式工作 我有一个返回列表的方法 private List
  • 如何列出所有可用的 LookAndFeel 主题?

    如何列出所有可用的 LookAndFeel 主题 我想在 JComboBox 中显示以供用户选择 这真的很简单 public static UIManager LookAndFeelInfo getInstalledLookAndFeels
  • 膨胀类片段 InflateException 二进制 XML 文件时出错

    我正在使用 Material Design 和 NavigationDrawer 布局等设计我的第一个应用程序 但我遇到了一个问题 该应用程序非常简单 它只显示文本 并且基于 Android Studio 中提供的模板 尝试启动我的应用程序
  • Hibernate @OneToMany 注释到底是如何工作的?

    我对 Hibernate 还很陌生 我正在通过教程学习它 我在理解到底如何一对多注释作品 所以我有这两个实体类 Student代表一个学生并且Guide代表指导学生的人 因此 每个学生都与一名向导相关联 但一名向导可以跟随多个学生 我想要一
  • C++ 中的 Java ArrayList [重复]

    这个问题在这里已经有答案了 在Java中我可以做 List
  • 使用成员作为实现者来实现接口

    我有实现 IA 的 A 类 现在我需要创建也应该实现 IA 的类 B B 类有 A 类的实例作为成员 有什么方法可以定义A的实例实现B类中的IA吗 interfase IA void method1 void method2 void me
  • 如何在 Java 中创建要打印到 JFrame 的 JLabels 数组

    我正在尝试制作一系列标签 每个标签都有一个来自函数的不同值 我不知道要使用的标签的确切数量 我的意思是可以打印任意数量的值 请帮我做这件事 很简单 只需一个方法返回一个数组或一些 JLabels 集合 并将它们全部添加到您的 JCompon
  • 如何防止字符串被截留

    我的理解 可能是错误的 是 在 C 中 当你创建一个字符串时 它会被实习到 实习生池 中 这保留了对字符串的引用 以便多个相同的字符串可以共享操作内存 但是 我正在处理很多很可能是唯一的字符串 一旦完成每个字符串 我需要将它们从操作内存中完
  • 为什么 RMI 注册表忽略 java.rmi.server.codebase 属性

    我正在运行 java RMI 的 Hello World 示例 1 我在空文件夹中运行注册表 motta motta laptop tmp rmiregistry 2 我启动 HTTP 服务器以在运行时检索类 下载文件夹包含客户端 服务器的
  • 以标准用户身份打开默认浏览器 (C++)

    我目前正在使用 ShellExecute 打开 在用户浏览器中打开 URL 但在 Win7 和 Vista 中遇到了一些麻烦 因为该程序作为服务运行提升 当 ShellExecute 打开浏览器时 它似乎读取 本地管理员 配置文件而不是用户
  • 在方法内声明类 - Final 关键字 [重复]

    这个问题在这里已经有答案了 给定方法中的以下内部类 IsSomething public class InnerMethod private int x public class Something private int y public
  • 在不使用 Thread.Sleep c# 的情况下延迟发送电子邮件

    我有一个 for 循环 它循环并每个循环发送一封电子邮件 现在我正在使用 thread sleep 但我希望用户仍然能够与程序交互 只需取消该循环即可 是否可以在不使用 thread sleep 的情况下做到这一点 您是否在 UI 线程上运
  • 如何用C++解析复杂的字符串?

    我试图弄清楚如何使用 解析这个字符串sstream 和C 其格式为 string int int 我需要能够将包含 IP 地址的字符串的第一部分分配给 std string 以下是该字符串的示例 std string 127 0 0 1 1
  • 无法将方法组“Read”转换为非委托类型“bool”

    我正在尝试使用SqlDataReader检查条目是否存在 如果存在则返回ID 否则返回false 当我尝试编译时 出现错误 无法将方法组 Read 转换为非委托类型 bool 我一直在遵循在 VB 中找到的示例 但似乎翻译可能不正确 pri
  • C 的“char”使用什么字符集? [复制]

    这个问题在这里已经有答案了 简单的问题 我最近开始用 C 编程 有一个简单的问题 C 编程语言在其 char 类型中使用什么字符集 例如 ASCII 还是取决于软件 操作系统 char 本质上是 1 个字节 主要在所有操作系统上 所以默认情
  • Jenkins 管道和 java.nio.file.* 方法的问题

    我正在尝试使用 java nio file 中的方法在 Jenkins 管道中执行一些基本文件操作 无论代码存在于哪个节点块中 代码都在主节点上执行 在管道中 我已经验证了各个节点块都是正确的 它们唯一地标识了特定的节点 但是 pathEx
  • 需要使用 openssl 加密和解密文件的示例 C 代码

    我正在用 Linux C 编写代码 我需要使用以下命令来加密和解密文件 openssl 目前 我使用系统命令 des3 e nosalt k 0123456789012345 in inp file out out file 进行加密 使用
  • 什么时候使用静态库需要头文件?

    如果我在 Linux 中用 C 创建一个静态库并生成 a 文件 我 或其他人 如何使用该库 例如 我的库定义了一个类 我认为仅仅提供 a 文件是不够的 还需要提供头文件 我如何知道 a 文件必须提供哪些头文件 例如 我是否需要提供我的库代码

随机推荐

  • 服务器 ping 不通有哪些原因导致的

    服务器 ping 不通有哪些原因导致的 太心急 即网线刚插到交换机上就想 Ping 通网关 忽略了生成树的收敛时间 当然 较新的交换机都支持快速生成树 或者有的管理员干脆把用户端口 access port 的生成树协议关掉 问题就解决了 某
  • 通过Git使用GitHub

    目录 一 建立个人仓库 二 配置SSH密钥 三 克隆仓库代码 四 推送代码到个人仓库 五 代码拉取 一 建立个人仓库 1 建立GitHub个人仓库 首先注册GitHub用户 注册好了之后 打开用户的界面 然后就是配置问题 配置好后拉到最下方
  • docker网络--多机通信--4--ingress笔记

    docker网络 多机通信 4 ingress 一 介绍 二 ingress网络 1 啥 2 增 3 删 4 改 5 查 三 ingress实验 1 说明 2 整体拓扑图 3 实验步骤 1 预置条件 2 步骤 4 原理说明 四 外部负载均衡
  • spring-bean的生命周期和怎么配置spring-bean的后置处理器

    前言 本章是spring基于XML 配置bean系类中第6篇讲解spring bean的生命周期和怎么配置spring bean的后置处理器 个人主页 尘觉主页 个人简介 大家好 我是尘觉 希望我的文章可以帮助到大家 您的满意是我的动力 在
  • 计算PI值到一亿位的算法 (转)

    计算PI值到一亿位的算法 转 more 我大体上考虑了一下用Delphi计算PI值到一亿位的算法 得到一个大体的算法 也好用来交流一下 这是一个构造一种新的长四则运算的算法 所谓长四则运算 是指用数据库的字段来作一个小数 用一个记录来作一个
  • 基于python的毕业设计仓库库存管理系统

    更多项目资源 最下方联系我们 目录 Python项目介绍 资料获取 Python项目介绍 计算机毕业设计python毕设项目之python仓库库存管理系统 IT实战课堂 哔哩哔哩 bilibili计算机毕业设计python毕设项目之pyth
  • 微信浏览器清理缓存的方法

    项目场景 项目包含电脑浏览器和手机的微信公众号两个部分 现在需要在微信端对项目进行测试 问题描述 在微信端打开项目的网页 发现某些部分的功能不如预期 退出微信并在服务器端进行修改 修改完成再次打开该网页 跟修改前的表现一样没有任何变化 原因
  • 企业u盘系统服务器,服务器u盘装系统

    服务器u盘装系统 内容精选 换一换 如果Linux操作系统云服务器未安装密码重置插件 可以参见本节内容重新设置密码 本节操作重置的是root用户的密码 您可以重置完root密码后登录云服务器后再更换秘钥或重置非root用户的密码 Windo
  • Group conv vs. Depthwise separable conv

    本王有话说 这俩属于是做轻量化绕不开的经典工作 盘踞武林好多年 我们的目标学会并企图超越它 分组卷积 Group conv paper 原理 分组卷积 即ResNeXt的亮点 受Inception和AlexNet的启发产生 Inceptio
  • 通过css样式定义span标签实现文本输入框功能

    span style width 200px height 24px line height 24px font size 14px padding 5px 8px border 1px solid ddd 我是文本输入框 span
  • TensorFlow学习过程记录 -- 问题解决

    在运行过程中 输出总是会产生两行警告信息 WARNING tensorflow From D python35 lib site packages tensorflow python util tf should use py 118 in
  • 机器学习中概率论知识复习

    机器学习先验知识概率论部分 发现看Machine Learning Andrew Ng 课程的时候中间有推导过程不是很明白 遂针对性复习 知识内容组织结构 参考 Probability Theory Review for Machine L
  • 使用PHP生成Excel文件并通过邮件发送

    需求 每周一自动检测一个月内即将过期的用户 生成excel2007文件 xlsx文件 并发送给指定的人员 做成一个脚本 使用定时任务即可解决 脚本分解为两步 生成Excel 发送邮件 一 生成Excel 使用简单的更改文件头 header
  • Java入门(6)——集合、基本数据类型和引用数据类型的相互转换

    集合 1 HashMap gt 类 概述 通过key可以找到value key就是键 values就是值 俗称键值对 特点 无序的 值可以重复 键不可以重复的 如果重复了 值就会覆盖 回顾 10 int num 10 jack String
  • Python基础内容:适合刚入门的朋友看的教程

    1 基本概念 1 1 四种类型 python中数有四种类型 整数 长整数 浮点数和复数 整数 如 1 长整数 是比较大的整数 浮点数 如 1 23 3E 2 复数 如 1 2 j 1 1 2 2j 1 2 字符串 字符串 字符的序列 pyt
  • ResNet50模型学习笔记

    ResNet的各种网络结构图如下图所示 ResNet的层级结构 Layer gt Block gt Stage gt Network Layer是最小的单位 ResNet50代表有50层 Block由两层或者三层conv层叠加而成 50层以
  • JavaWeb-form传值(从一个jsp页面传数据到另一个jsp页面)

    第一个页面 login jsp
  • OkHttpClient获取文件并下载

    需要调用第三方接口获取文件 本地通过网页直接下载 public Result doExcelExport String repoId HttpServletResponse response try if StringUtils isBla
  • nginx配置指南

    nginx conf配置 找到Nginx的安装目录下的nginx conf文件 该文件负责Nginx的基础功能配置 配置文件概述 Nginx的主配置文件 conf nginx conf 按以下结构组织 配置块 功能描述 全局块 与Nginx
  • 行为型设计模式之策略模式【设计模式系列】

    系列文章目录 C 技能系列 Linux通信架构系列 C 高性能优化编程系列 深入理解软件架构设计系列 高级C 并发线程编程 设计模式系列 期待你的关注哦 现在的一切都是为将来的梦想编织翅膀 让梦想在现实中展翅高飞 Now everythin