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

【第14节】C++设计模式(行为模式)-Strategy (策略)模式

一、问题的提出

Strategy 模式:算法实现与抽象接口的解耦

        Strategy 模式和 Template 模式要解决的问题是相似的,都是为了将业务逻辑(算法)的具体实现与抽象接口解耦。Strategy 模式通过将算法封装到一个类(Context)中,并通过组合的方式将具体算法的实现委托给组合对象来完成。

二、模式选择

Strategy 模式的典型结构如下图所示:

        其核心思想是将算法的逻辑抽象接口(如 `DoAction`)封装到一个类中(Context),然后通过委托的方式将具体的算法实现交给具体的 Strategy 类(如 `ConcreteStrategyA` 和 `ConcreteStrategyB`)来完成。

三、代码实现

以下是 Strategy 模式的完整实现代码,采用 C++ 编写。

代码实现

Strategy.h

#ifndef _STRATEGY_H_
#define _STRATEGY_H_// 抽象策略类,定义算法接口
class Strategy {
public:Strategy() {}virtual ~Strategy() {}virtual void AlgorithmInterface() = 0;  // 算法接口,子类实现
};// 具体策略类A,实现算法接口
class ConcreteStrategyA : public Strategy {
public:ConcreteStrategyA() {}virtual ~ConcreteStrategyA() {}void AlgorithmInterface() override;  // 实现算法接口
};// 具体策略类B,实现算法接口
class ConcreteStrategyB : public Strategy {
public:ConcreteStrategyB() {}virtual ~ConcreteStrategyB() {}void AlgorithmInterface() override;  // 实现算法接口
};#endif //~_STRATEGY_H_

Strategy.cpp

#include "Strategy.h"
#include <iostream>
using namespace std;// 具体策略类A的算法实现
void ConcreteStrategyA::AlgorithmInterface() {cout << "ConcreteStrategyA: AlgorithmInterface" << endl;
}// 具体策略类B的算法实现
void ConcreteStrategyB::AlgorithmInterface() {cout << "ConcreteStrategyB: AlgorithmInterface" << endl;
}

Context.h

#ifndef _CONTEXT_H_
#define _CONTEXT_H_class Strategy;/*** Context 类是 Strategy 模式的关键,也是 Strategy 模式和 Template 模式的主要区别所在。* Strategy 模式通过组合(委托)的方式实现算法的异构,而 Template 模式则通过继承的方式实现。*/
class Context {
public:Context(Strategy* strategy);  // 构造函数,传入具体策略~Context();void DoAction();  // 执行策略
private:Strategy* _strategy;  // 组合的策略对象
};#endif //~_CONTEXT_H_

Context.cpp

#include "Context.h"
#include "Strategy.h"
#include <iostream>
using namespace std;// 构造函数,初始化策略对象
Context::Context(Strategy* strategy) : _strategy(strategy) {}// 析构函数,释放策略对象
Context::~Context() {if (_strategy) {delete _strategy;}
}// 执行策略
void Context::DoAction() {_strategy->AlgorithmInterface();
}

main.cpp

#include "Context.h"
#include "Strategy.h"
#include <iostream>
using namespace std;int main(int argc, char* argv[]) {Strategy* strategyA = new ConcreteStrategyA();  // 创建具体策略AContext* contextA = new Context(strategyA);     // 创建上下文,传入策略AcontextA->DoAction();                          // 执行策略AStrategy* strategyB = new ConcreteStrategyB();  // 创建具体策略BContext* contextB = new Context(strategyB);     // 创建上下文,传入策略BcontextB->DoAction();                          // 执行策略Bdelete contextA;delete contextB;return 0;
}

代码说明

        Strategy 模式的实现非常直观,其核心思想是将算法的逻辑封装到一个类中,并通过组合的方式将具体算法的实现委托给组合对象。Context 类通过持有 Strategy 对象的指针,动态调用具体的算法实现。

四、总结讨论

        Strategy 模式和 Template 模式解决了类似的问题,但它们采用了不同的实现方式:Strategy 模式通过组合(委托)实现算法的异构,而 Template 模式则通过继承实现。这两种方式各有优缺点:

继承的优缺点

优点:
(1)易于修改和扩展被复用的实现。

缺点:
(1)破坏了封装性,父类的实现细节暴露给子类;
(2)属于“白盒”复用;
(3)当父类的实现更改时,所有子类都需要随之改变;
(4)继承的实现在运行期间不能改变(编译期间已确定)。

组合的优缺点

优点:
(1)属于“黑盒”复用,被包含对象的内部细节对外不可见;
(2)封装性好;
(3)实现和抽象的依赖性小;
(4)可以在运行期间动态定义实现(通过抽象基类的指针)。

缺点:
(1)系统中对象可能过多。

        从上述对比可以看出,组合相比继承具有更好的灵活性和封装性。因此,在面向对象设计中,有一条重要的原则:优先使用对象组合,而非类继承(Favor Composition Over Inheritance)。

        Strategy 模式通过组合的方式实现了算法与抽象接口的解耦,适用于需要在运行时动态切换算法的场景。与 Template 模式相比,Strategy 模式更加灵活,避免了继承带来的强耦合性。在实际开发中,优先使用组合而非继承,可以显著提高代码的可维护性和扩展性。

相关文章:

【第14节】C++设计模式(行为模式)-Strategy (策略)模式

一、问题的提出 Strategy 模式&#xff1a;算法实现与抽象接口的解耦 Strategy 模式和 Template 模式要解决的问题是相似的&#xff0c;都是为了将业务逻辑&#xff08;算法&#xff09;的具体实现与抽象接口解耦。Strategy 模式通过将算法封装到一个类&#xff08;Context&am…...

播放器系列4——PCM重采样

FFmpeg重采样过程 #mermaid-svg-QydNPsDAlg9lTn6z {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QydNPsDAlg9lTn6z .error-icon{fill:#552222;}#mermaid-svg-QydNPsDAlg9lTn6z .error-text{fill:#552222;stroke:#5…...

网络安全需要学多久才能入门?

网络安全是一个复杂且不断发展的领域&#xff0c;想要入行该领域&#xff0c;我们需要付出足够多的时间和精力好好学习相关知识&#xff0c;才可以获得一份不错的工作&#xff0c;那么网络安全需要学多久才能入门?我们通过这篇文章来了解一下。 学习网络安全的入门时间因个人的…...

通俗版解释:分布式和微服务就像开餐厅

一、分布式系统&#xff1a;把大厨房拆成多个小厨房 想象你开了一家超火爆的餐厅&#xff0c;但原来的厨房太小了&#xff1a; 问题&#xff1a;一个厨师要同时切菜、炒菜、烤面包&#xff0c;手忙脚乱还容易出错。 解决方案&#xff1a; 拆分成多个小厨房&#xff08;分布式…...

JAVA安全—手搓内存马

前言 最近在学这个内存马&#xff0c;就做一个记录&#xff0c;说实话这个内存马还是有点难度的。 什么是内存马 首先什么是内存马呢&#xff0c;顾名思义就是把木马打进内存中。传统的webshell一旦把文件删除就断开连接了&#xff0c;而Java内存马则不同&#xff0c;它将恶…...

【神经网络】python实现神经网络(一)——数据集获取

一.概述 在文章【机器学习】一个例子带你了解神经网络是什么中&#xff0c;我们大致了解神经网络的正向信息传导、反向传导以及学习过程的大致流程&#xff0c;现在我们正式开始进行代码的实现&#xff0c;首先我们来实现第一步的运算过程模拟讲解&#xff1a;正向传导。本次代…...

历年湖南大学计算机复试上机真题

历年湖南大学计算机复试机试真题 在线评测&#xff1a;https://app2098.acapp.acwing.com.cn/ 杨辉三角形 题目描述 提到杨辉三角形。 大家应该都很熟悉。 这是我国宋朝数学家杨辉在公元 1261 年著书《详解九章算法》提出的。 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 …...

[LeetCode]day33 150.逆波兰式求表达值 + 239.滑动窗口最大值

逆波兰式求表达值 题目链接 题目描述 给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意&#xff1a; 有效的算符为 ‘’、‘-’、‘*’ 和 ‘/’ 。 每个操作数&#xff08;运…...

【银河麒麟高级服务器操作系统实际案例分享】数据库资源重启现象分析及处理全过程

更多银河麒麟操作系统产品及技术讨论&#xff0c;欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer…...

C#中泛型的协变和逆变

协变&#xff1a; 在泛型接口中&#xff0c;使用out关键字可以声明协变。这意味着接口的泛型参数只能作为返回类型出现&#xff0c;而不能作为方法的参数类型。 示例&#xff1a;泛型接口中的协变 假设我们有一个基类Animal和一个派生类Dog&#xff1a; csharp复制 public…...

【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-附录B-严格模式

附录B、严格模式 严格模式 ECMAScript 5 首次引入严格模式的概念。严格模式用于选择以更严格的条件检查 JavaScript 代码错误&#xff0c;可以应用到全局&#xff0c;也可以应用到函数内部。严格模式的好处是可以提早发现错误&#xff0c;因此可以捕获某些 ECMAScript 问题导致…...

跨平台 C++ 程序崩溃调试与 Dump 文件分析

前言 C 程序在运行时可能会由于 空指针访问、数组越界、非法内存访问、栈溢出 等原因崩溃。为了分析崩溃原因&#xff0c;我们通常会生成 Dump 文件&#xff08;Windows 的 .dmp&#xff0c;Linux 的 core&#xff0c;macOS 的 .crash&#xff09;&#xff0c;然后用调试工具分…...

缺陷VS质量:为何软件缺陷是质量属性的致命对立面?

为何说缺陷是质量的对立面&#xff1f; 核心逻辑&#xff1a;软件质量的定义是“满足用户需求的程度”&#xff0c;而缺陷会直接破坏这种满足关系。 对立性&#xff1a;缺陷的存在意味着软件偏离了预期行为&#xff08;如功能错误、性能不足、安全性漏洞等&#xff09;&#…...

伍[5],伺服电机,电流环,速度环,位置环

电流环、速度环和位置环是电机控制系统中常见的三个闭环控制环节,通常采用嵌套结构(内环→外环:电流环→速度环→位置环),各自负责不同层级的控制目标。以下是它们的详细说明及相互关系: 1. 电流环(最内环) 作用:控制电机的电流,间接控制输出转矩(τ=Kt⋅Iτ=Kt​⋅…...

RuntimeError: CUDA error: device-side assert triggered

RuntimeError: CUDA error: device-side assert triggered 欢迎来到英杰社区&#xff0c;这里是博主英杰https://bbs.csdn.net/topics/617804998 原因&#xff1a; cuda运行可能是异步的&#xff08;asynchronously&#xff09;&#xff0c;因此报错信息中提示的位置可能不准确…...

清华大学Deepseek第六版AIGC发展研究3.0(共186页,附PDF下载)

人工智能生成内容&#xff08;AIGC&#xff09;正以前所未有的速度改变我们的生活。 2024年底&#xff0c;清华大学新闻与传播学院与人工智能学院联合发布了《AIGC发展研究3.0版》&#xff0c;这份报告系统梳理了AIGC技术的突破性进展、应用场景及社会影响&#xff0c;并展望了…...

SpringBoot生成唯一ID的方式

1.为什么要生成唯一ID&#xff1f; 数据唯一性&#xff1a;每个记录都需要有一个独一无二的标识符来确保数据的唯一性。这可以避免重复的数据行&#xff0c;并有助于准确地查询、更新或删除特定的记录。 数据完整性&#xff1a;通过使用唯一ID&#xff0c;可以保证数据库中的数…...

通俗易懂的分类算法之K近邻详解

通俗易懂的分类算法之K近邻详解 用最通俗的语言和例子&#xff0c;来彻底理解 K近邻&#xff08;K-Nearest Neighbors&#xff0c;简称 KNN&#xff09; 这个分类算法。不用担心复杂的数学公式&#xff0c;我会用生活中的例子来解释&#xff0c;保证你一听就懂&#xff01; 1.…...

CSDN markdown 操作指令等

CSDN markdown 操作指令等 页内跳转 [内容](#1) <div id"1"> </div>...

【linux】文件与目录命令 - uniq

文章目录 1. 基本用法2. 常用参数3. 用法举例4. 注意事项 uniq 命令用于过滤文本文件中相邻的重复行&#xff0c;并支持统计重复次数或仅保留唯一行。它通常与 sort 命令配合使用&#xff0c;因为 uniq 只识别相邻的重复行。 1. 基本用法 语法&#xff1a; uniq [选项] [输入…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

前端高频面试题2:浏览器/计算机网络

本专栏相关链接 前端高频面试题1&#xff1a;HTML/CSS 前端高频面试题2&#xff1a;浏览器/计算机网络 前端高频面试题3&#xff1a;JavaScript 1.什么是强缓存、协商缓存&#xff1f; 强缓存&#xff1a; 当浏览器请求资源时&#xff0c;首先检查本地缓存是否命中。如果命…...

aardio 自动识别验证码输入

技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”&#xff0c;于是尝试整合图像识别与网页自动化技术&#xff0c;完成了这套模拟登录流程。核心思路是&#xff1a;截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...