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

2.策略模式(Strategy)

定义

定义一系列算法,把它们一个个封装起来,并且使他们可互相替换(变化)。该模式使算法可独立于使用它的客户程序(稳定)而变化(拓展,子类化)。

动机(Motivation)

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

例如在电子商务中的一个税种订单计算。我们首先想到的实现方法是先定义一个枚举类型,定义出中国美国德国的税法计算。
在涉及到税法计算中 CalculateTax 我们通过这个枚举类型进行相应的计算。

enum TaxBase {CN_Tax, // 中国US_Tax, // 美国DE_Tax, // 德国
};class SalesOrder{TaxBase tax;
public:double CalculateTax(){//...if (tax == CN_Tax){//CN***********}else if (tax == US_Tax){//US***********}else if (tax == DE_Tax){//DE***********} //....}};

比方说 未来出现变化了,需要支持 法国的税法。
首先需要在枚举类型 TaxBase 中增加一个枚举类型 FR_Tax //法国,
然后再 CalculateTax 中继续添加 if (tax == FR_Tax)
完整代码如下:

enum TaxBase {CN_Tax,US_Tax,DE_Tax,FR_Tax       //更改
};class SalesOrder{TaxBase tax;
public:double CalculateTax(){//...if (tax == CN_Tax){//CN***********}else if (tax == US_Tax){//US***********}else if (tax == DE_Tax){//DE***********}else if (tax == FR_Tax){  //更改//...}//....}};

很显然上面的代码违反了 开放封闭原则,即对拓展开发,对更改封闭。就是类模块尽可能用拓展的方式来支持未来的变化,而不是直接修改源代码。

下面开始改进

  1. 首先不使用枚举类型 ,而是定义一个税法策略的基类
    它有一个计算的方法 Calculate,是纯虚函数
class TaxStrategy{
public:virtual double Calculate(const Context& context)=0;virtual ~TaxStrategy(){}
};

2.对于各个国家的税法,我们进行单独的计算,其实就是将

  if (tax == CN_Tax){//CN***********}

类似这部分 CN … US … 等这类算法部分 放到类的纯虚函数中,变成 TaxStrategy 的子类。

class CNTax : public TaxStrategy{
public:virtual double Calculate(const Context& context){//***********}
};class USTax : public TaxStrategy{
public:virtual double Calculate(const Context& context){//***********}
};class DETax : public TaxStrategy{
public:virtual double Calculate(const Context& context){//***********}
};
  1. 创建多态指针 TaxStrategy * strategy ,这里使用的是外界传入的,这里可能返回的是 DETax 或 USTax 或 CNTax 等的对象,至于是哪一个,由工厂模式确定,在 SalesOrder(StrategyFactory* strategyFactory) 中的函数参数传入。如果传入是 USTax 那么就是美国。
    首先构建算法上下文 Context context(); ,然后直接调用
    strategy->Calculate(context); 这就是一个多态调用,可能会调用 中国税法,也可能调用美国,或其它。
  2. 从时间轴看好处。加入增加一个法国的税计算,那么只需要增加
    class FRTax : public TaxStrategy{
    public:
    virtual double Calculate(const Context& context){
    //***********
    }
    };
    然后其他的代码就不需要改变。

完整代码如下:


class SalesOrder{
private:// 这里期望这个指针指向不同的strategy的子类TaxStrategy* strategy;public:SalesOrder(StrategyFactory* strategyFactory){// 实例化一个对象this->strategy = strategyFactory->NewStrategy();}~SalesOrder(){delete this->strategy;}public double CalculateTax(){//...Context context();double val = strategy->Calculate(context); //多态调用//...}};

class TaxStrategy{
public:virtual double Calculate(const Context& context)=0;virtual ~TaxStrategy(){}
};class CNTax : public TaxStrategy{
public:virtual double Calculate(const Context& context){//***********}
};class USTax : public TaxStrategy{
public:virtual double Calculate(const Context& context){//***********}
};class DETax : public TaxStrategy{
public:virtual double Calculate(const Context& context){//***********}
};//扩展
//*********************************
class FRTax : public TaxStrategy{
public:virtual double Calculate(const Context& context){//.........}
};class SalesOrder{
private:// 这里期望这个指针指向不同的strategy的子类TaxStrategy* strategy;public:SalesOrder(StrategyFactory* strategyFactory){// 实例化一个对象this->strategy = strategyFactory->NewStrategy();}~SalesOrder(){delete this->strategy;}public double CalculateTax(){//...Context context();double val = strategy->Calculate(context); //多态调用//...}};

总结

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

Strategy 模式提供了用条件判断语句之外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要 Strategy 模式。

如果 Strategy 对象没有实例变量,那么各个上传下文可以共享同一个 Strategy 对象,从而节省对象开销。

相关文章:

2.策略模式(Strategy)

定义 定义一系列算法,把它们一个个封装起来,并且使他们可互相替换(变化)。该模式使算法可独立于使用它的客户程序(稳定)而变化(拓展,子类化)。 动机(Motiva…...

Python里的小整数问题挺有意思的

简单来说,Python为了优化性能,会把一些常用的整数(通常是-5到256)提前创建好,放到一个“缓存池”里。这样,当你用到这些小整数时,Python就不用每次都重新创建对象了,直接从缓存池里拿…...

开源智慧园区管理系统对比五款主流产品探索智能运营新模式

内容概要 在这个数字化迅速发展的时代,园区管理也迎来了全新的机遇和挑战。众所周知,开源智慧园区管理系统作为一种创新解决方案,正逐步打破传统管理的局限性。它的开放性不仅使得系统可以根据具体需求进行灵活调整,也为用户提供…...

正则表达式入门

入门 1、提取文章中所有的英文单词 //1.先创建一个Pattern对象,模式对象,可以理解成就是一个正则表达式对象 Pattern pattern Pattern.compile("[a-zA-Z]"); //2.创建一个匹配器对象 //理解:就是 matcher匹配器按照p…...

hive:数据导入,数据导出,加载数据到Hive,复制表结构

hive不建议用insert,因为Hive是建立在Hadoop之上的数据仓库工具,主要用于批处理和大数据分析,而不是为OLTP(在线事务处理)操作设计的。INSERT操作会非常慢 数据导入 命令行界面:建一个文件 查询数据>>复制>>粘贴到新…...

【某大厂一面】HashSet底层怎么实现的

HashSet 是 Java 集合框架中的一个非常常用的集合类,它实现了 Set 接口,并且底层通常是通过 哈希表(HashMap)来实现的。要理解 HashSet 的底层实现,我们需要从哈希表的工作原理开始讲起。下面是对 HashSet 底层实现的详…...

动手学图神经网络(3):利用图神经网络进行节点分类 从理论到实践

利用图神经网络进行节点分类:从理论到实践 前言 在之前的学习中,大家对图神经网络有了初步的了解。本次教程将深入探讨如何运用图神经网络(GNNs)来解决节点分类问题。在节点分类任务里,大家往往仅掌握少量节点的真实标签,却要推断出其余所有节点的标签,这属于归纳式学…...

免杀国内主流杀软的恶意样本分析

目录下存在愤怒的小鸟.exe和fun.dll文件,最新版火绒,windows defender,腾讯电脑管家,360静态扫描都未发现恶意程序 动态执行,杀软也未拦截 上传到virustotal网站分析恶意程序,只有三个引擎检测出来 die分析…...

第4章 基于中点电流的NPC逆变器中点电压平衡策略

1. 工作原理 1.1 NPC型三电平逆变器工作原理 NPC型三相三电平逆变器有A、B、C三个桥臂,其组成结构是相同的,本章以A相为例,对其工作原理进行分析。开关器件SA1和SA3、SA2和SA4为互补器件,通过控制开关器件的导通和关断状态&#…...

消息队列篇--通信协议篇--应用层协议和传输层协议理解

在网络通信中,传输层协议和应用层协议是OSI模型中的两个不同层次的协议,它们各自承担着不同的职责。 下文中,我们以TCP/UDP(传输层协议)和HTTP/SMTP(应用层协议)为例进行详细解释。 1、传输层协…...

FLTK - FLTK1.4.1 - demo - animgifimage

文章目录 FLTK - FLTK1.4.1 - demo - animgifimage概述笔记END FLTK - FLTK1.4.1 - demo - animgifimage 概述 知识点: 注册图像文件类型判断回调 FLTK支持的图像格式 GIF, BMP, ICO, PNM, PNG, jpg, svg 事件回调的注册 GIF图像显示为图片或动画的标志设置 // 超时回调的设置…...

目前市场主流的AI PC对于大模型本地部署的支持情况分析-Deepseek

以下是目前市场主流AI PC对**大模型本地部署支持情况**的综合分析,结合硬件能力、软件生态及厂商动态进行总结: --- ### **一、硬件配置与算力支持** 1. **核心处理器架构** - **异构计算方案(CPUGPUNPU)**:主流…...

1.2 基于深度学习的底层视觉技术

文章目录 高层视觉任务与底层视觉任务深度神经网络相对于传统方法的优势 高层视觉任务与底层视觉任务 计算机视觉中的任务包含高层视觉任务,底层视觉任务。高层视觉任务是处理语义级别相关的任务,例如图像分类、目标检测、图像分割等。底层视觉任务处理与…...

HTML 标题

HTML 标题 引言 HTML(超文本标记语言)是构建网页的基础,而标题则是网页中不可或缺的元素。标题不仅能够帮助用户快速了解网页内容,还能够对搜索引擎优化(SEO)产生重要影响。本文将详细介绍HTML标题的用法…...

SOME/IP--协议英文原文讲解3

前言 SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块: 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 Note: Thi…...

Microsoft Visual Studio 2022 主题修改(补充)

Microsoft Visual Studio 2022 透明背景修改这方面已经有很多佬介绍过了,今天闲来无事就补充几点细节。 具体的修改可以参考:Microsoft Visual Studio 2022 透明背景修改(快捷方法)_material studio怎么把背景弄成透明-CSDN博客文…...

UE(UltraEdit) 配置简易C/C++编译运行环境

该类型其他帖子 EmEditor 配置简易C/C 编译运行环境_emeditor 代码运行-CSDN博客 RJ TextEd 配置简易C/C 编译运行环境-CSDN博客 这种配置适合ACM竞赛,即要求不使用现代IDE,又想用一个比较好用、至少支持代码高亮的编辑器。 前提条件 1.Mingw GCC 已…...

使用 MSYS2 qemu 尝鲜Arm64架构国产Linux系统

近期,我的师弟咨询我关于Arm64架构的国产CPU国产OS开发工具链问题。他们公司因为接手了一个国企的单子,需要在这类环境下开发程序。说实在的我也没有用过这个平台,但是基于常识,推测只要基于C和Qt,应该问题不大。 1. …...

python Flask-Redis 连接远程redis

当使用Flask-Redis连接远程Redis时,首先需要安装Flask-Redis库。可以通过以下命令进行安装: pip install Flask-Redis然后,你可以使用以下示例代码连接远程Redis: from flask import Flask from flask_redis import FlaskRedisa…...

在Windows系统中本地部署属于自己的大语言模型(Ollama + open-webui + deepseek-r1)

文章目录 1 在Windows系统中安装Ollama,并成功启动;2 非docker方式安装open-webui3下载并部署模型deepseek-r1 Ollama Ollama 是一个命令行工具,用于管理和运行机器学习模型。它简化了模型的下载与部署,支持跨平台使用&#xff0c…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

基于服务器使用 apt 安装、配置 Nginx

🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...