C++设计模式 #3策略模式(Strategy Method)

2023-12-21

动机

  • 在软件构建过程中,某些对象使用的的算法可能多种多样,经常改变。如果将这些算法都写在类中,会使得类变得异常复杂;而且有时候支持不频繁使用的算法也是性能负担。

如何在运行时根据需求透明地更改对象的算法?将算法和对象本身解耦,从而避免上述问题?

举个栗子

我们假设现在有一个需求,需要对不同的颜色做不同的策略(算法)。

enum Color {
	RED,
	BLUE
};

class strategy {
private:
	Color color;
public:
	void strategy_func() {
		if (color == RED) {
			//do something
		}
		else if (color == BLUE) {
			// do something else
		}
	}
};

以上是比较经典的做法,使用一个枚举类型来指定当前的颜色,对不同的颜色做不同的处理。

那么,如果需求改变了,新增了一个粉色,那么代码需要做如下更改

enum Color {
	RED,
	BLUE,
	PINK    //变化
};

class strategy {
private:
	Color color;
public:
	void strategy_func() {
		if (color == RED) {
			//do something
		}
		else if (color == BLUE) {
			// do something else
		}
		else if (color == PINK) {    //变化
			// do sth with pink
		}
	}
};

这样的作法虽然可行,但是违背了开放封闭(OCP)的设计原则。也就是类模块是可扩展的,但是不要修改。

设计模式的原则详见:)C++设计模式#1-CSDN博客

策略模式做法

我们修改我们的类如下

class strategy {
public:
	virtual void func() = 0;
	virtual ~strategy(){}
};

class REDstrategy :public strategy {
	virtual void func() {
		// do something
	}
};

class BLUEstrategy :public strategy {
	virtual void func() {
		// do something
	}
};

class PINKstrategy :public strategy {
	virtual void func() {
		// do something
	}
};

class solution {
private:
	strategy* pointer;
public:
	void solute() {
		// ...
		//	确认颜色
		//	或者在构造函数中确认颜色
		//	即pointer指针指向哪个子类
		pointer->func();
		//...
	}
};

我们将对应不同颜色的方法,修改成从同一个基类中继承出来的子类。

在最后的solution中,使用基类的指针,使用多态思想来确认颜色和对应的处理方法,并调用。

这样在新的需求到达的时候,我们只需要新增一个继承出的子类并实现对应的算法即可。其他方法都不需要修改。(如何在solution过程中确定是否是新增的颜色,可以在构造函数中使用工厂设计模式)

模式定义

定义一系列算法,将它们一个个封装起来,并且使它们可以相互替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。——《设计模式》

结合上面的代码理解模式的定义,互相替换也就是也就是PINKstrategy类的添加。独立于客户程序也就是solution类,保证了solution类的稳定,变化指多态地使用不同颜色子类的func()。

红色圈中的是稳定的部分,也就是对应以上的strategy和solution类。蓝色圈中的是变化的部分,也就是以上的对应各个颜色的子类。

总结

  • 策略模式及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需求在各个算法之间进行切换。

运行时

多态的指针的子类方法就实现了运行时确定的需求。

  • 策略模式给很多if-else语句结构提供了另外一种解决方案。
  • 在负载方面。如果strategy对象没有实例变量,那么上下文可以共享同一个strategy对象,从而节省对象开销。

并且,大段的if-else代码不用加载到内存中

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++设计模式 #3策略模式(Strategy Method) 的相关文章

  • 为什么两个不同的 Base64 字符串的转换会返回相等的字节数组?

    我想知道为什么从 base64 字符串转换会为不同的字符串返回相同的字节数组 const string s1 dg const string s2 dq byte a1 Convert FromBase64String s1 byte a2
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 按成员序列化

    我已经实现了template
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags

随机推荐

  • 【taro react】---- 解决 iOS 真机微信小程序 Input 密码框 type 切换会导致 Input 内容丢失问题

    1 问题场景 在密码登陆时 有显示和隐藏密码的功能 实现方式很简单 直接对输入 input 的 type 进行 password 和 text 值进行切换 就可以实现密码的显示和隐藏 2 实现代码 通过修改 input 的 type 值实现
  • 【taro react】---- 解决 taro 编译 H5 姓名脱敏导致的 iOS 部分低版本白屏问题

    1 姓名脱敏方法 判断传入字段是否是字符串 将字符串除第一个字符后的其他字符全部替换为 const replaceUserName name gt if isTypingMathods isString name return name r
  • 【已解决】vs2015下QtnetWork No Such File or Directory报错

    源于笔者在做qt工具时 遇到的一个问题 问题很直观 加载第三方文件时 第三方文件调用了 include
  • Goby 漏洞发布| Apusic 应用服务器 createDataSource 远程代码执行漏洞

    漏洞名称 Apusic 应用服务器 createDataSource 远程代码执行漏洞 English Name Apusic Application Server loadTree Remote Code Execution Vulner
  • Hamming space

    汉明距离表示两个相同长度字符串对应位置的不同字符的数量 对两个字符串异或运算 并统计1的个数并相减 这个数就是汉明距离
  • Tomcat远程调试

    windows环境 写一个 startup debug bat 指定tomcat的根目录 端口自己定义 rem 设置Tomcat目录 set CATALINE HOME D asd A8 2 tomcat d rem 8787为可用端口 为
  • 互联网加竞赛 python+深度学习+opencv实现植物识别算法系统

    0 前言 优质竞赛项目系列 今天要分享的是 基于深度学习的植物识别算法研究与实现 学长这里给一个题目综合评分 每项满分5分 难度系数 4分 工作量 4分 创新点 4分 更多资料 项目分享 https gitee com dancheng s
  • test和我说过

    27车型管理 年代需提示 SOP当年时间 且只显示两位数 如2024只最示24未部署生产 29车型管理 网络选项值不全未部署生产 31车型管理 系统需限制车型计划开始时间与结束时间需包含在车型管理开始时间与结束时间之间未部署uat 需要提手
  • MySQL SELECT:数据表查询语句

    在 MySQL 中 可以使用 SELECT 语句来查询数据 查询数据是指从数据库中根据需求 使用不同的查询方式来获取不同的数据 是使用频率最高 最重要的操作 SELECT 的语法格式如下 SELECT lt 字段列名 gt FROM lt
  • 速通Python基础语法--运算符篇

    一 算术运算符 优先级 除法的2个问题 除零异常 运行时才出现的错误 叫做 抛出异常 如果程序运行过程中 抛出异常 程序就会直接终止 后面的代码不会执行 除法的 不 截断问题 取模 求余数 乘方 开方 向下 小 取整 地板除 二 关系运算符
  • 基于python的超市购物系统的设计与实现

    摘 要 随着国内市场经济这几十年来的蓬勃发展 突然遇到了从国外传入国内的互联网技术 互联网产业从开始的群众不信任 到现在的离不开 中间经历了很多挫折 从当初的传统销售行业抵制互联网销售 到现在传统销售与网络销售的结合模式 都代表着网络购物是
  • 【计算机毕设文章】传染病防控宣传系统小程序

    设计题目 传染病防控宣传系统的设计与实现 摘 要 由于APP软件在开发以及运营上面所需成本较高 而用户手机需要安装各种APP软件 因此占用用户过多的手机存储空间 导致用户手机运行缓慢 体验度比较差 进而导致用户会卸载非必要的APP 倒逼管理
  • 【计算机毕设文章】微信互助学习平台

    微信互助学习平台 摘要 随着信息技术在管理上越来越深入而广泛的应用 管理信息系统的实施在技术上已逐步成熟 本文介绍了微信互助学习平台的开发全过程 通过分析微信互助学习平台管理的不足 创建了一个计算机管理微信互助学习平台的方案 文章介绍了微信
  • Java版工程行业管理系统源码-专业的工程管理软件- 工程项目各模块及其功能点清单

    工程项目管理软件是现代项目管理中不可或缺的工具 它能够帮助项目团队更高效地组织和协调工作 本文将介绍一款功能强大的工程项目管理软件 该软件采用先进的Vue Uniapp Layui等技术框架 涵盖了项目策划决策 规划设计 施工建设到竣工交付
  • R语言——基本操作(二)

    目录 一 矩阵与数组 二 列表 三 数据框 四 因子 五 缺失数据 六 字符串 七 日期和时间 参考 一 矩阵与数组 matrix 创建矩阵 nrow 和 ncol 可以省略 但其值必须满足分配条件 否则会报错 只写一个值则自动分配 默认按
  • Leetcode 55 跳跃游戏

    题意理解 非负整数数组 nums 最初位于数组的 第一个下标 数组中的每个元素代表你在该位置可以跳跃的最大长度 需要跳到nums最后一个元素即为成功 目标 是否能够跳到最后一个元素 解题思路 使用贪心算法来解题 需要理解局部解和最优解的关系
  • 网络基础介绍

    1 网线制作 1 1 网线制作需要的工具 网线 网线钳 水晶头 测试仪 编辑 1 2 网线的标准 1 3 网线的做法 2 集线器 交换机 路由器的介绍 3 OSI七层模型 4 路由器的设置 4 1 常见的路由器设置地址 4 2 常见的路由器
  • C++设计模式 #3策略模式(Strategy Method)

    动机 在软件构建过程中 某些对象使用的的算法可能多种多样 经常改变 如果将这些算法都写在类中 会使得类变得异常复杂 而且有时候支持不频繁使用的算法也是性能负担 如何在运行时根据需求透明地更改对象的算法 将算法和对象本身解耦 从而避免上述问题
  • WinSync.dll文件丢失导致程序无法运行问题

    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题 如果是新手第一时间会认为是软件或游戏出错了 其实并不是这样 其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库 这时你可以下载这个WinSync
  • 达芬奇18.6DaVinci ResolveStudio(Win/Mac)激活版

    DaVinci Resolve Studio 18是一款业界领先的视频后期制作软件 它集成了剪辑 调色 视觉特效 动态图形和音频后期制作等功能 为用户提供了完整的创作解决方案 该软件不仅适用于电影 电视和网页内容的制作 还广泛应用于广告 纪