C++设计模式:策略模式(二)

news2024/11/20 2:35:17
1、定义与动机
  • 定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化),该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)

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

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

2、举例
  • 对于一个跨境电商的软件来说计算不同国家的税收、货币结算是一个非常常见的事情
  • 而通产来说每个国家的税的计算方式并不相同,每个国家都有其自己的税换算算法
  • 这里的设计也存在一定的门路,如果换成代码层面来看
2.1、结构化软件设计流程

这种做法很简单:

  • 首先定义一个枚举类,将不同国家的税率计算方式定义出来(这个可以不需要)只是为了使用方便
  • 然后定义销售订单类,里面定义计算税的方法,具体的实现通过大量的if-else if-else来具体调用
  • 对于这样的一个计算税的方法,calculate方法过于庞大,主要存在两个问题:
    • 违背开闭原则(OCR):当这个海外电商需要新增一个上线的国家,那么需要修改TaxBase枚举类,其次需要在计算方法里面增加这个国家的税计算方式,很明显违背修改关闭拓展开放的原则
    • 性能负担:其实这个软件在一个国家上线后大量的其他国家的税计算方式并不关心,但是在代码中强行硬编码写入!运行起来的代码段充斥着大量的无关代码!导致性能的下降
enum TaxBase{
    CN_Tax,                 // 国内税
    US_Tax,                 // 美国税
    DE_Tax                  // 德国税
    /*
    如果需要增加,需要在这里继续枚举的定义....
    JP_Tax,
    FR_Tax
    */
};

class SalesOrder{
private:
    TaxBase tax;
public:
    double calculateTax(){
        //...
        if(tax == CN_Tax){
            // CN*****
        }
        else if(tax == US_Tax){
            // US*****
        }
        else if(tax == DE_Tax){
            // DE*****
        }
        // 这里需要增加拓展国家税的计算方式
    }
};
2.2、策略模式
  • 策略模式:当代码中存在大量的if-else if-else或者switch-case时,就应该考虑使用策略模式来优化
  • 实现思路思考:
    • 首先定义一个计算税的抽象基类TaxStrategy
    • 对于不同的国家计算方式定义不同的类继承TaxStrategy基类,并且实现其计算calculateTax方法
    • 然后在需要使用计算的代码中聚合/组合一个基类TaxStrategy的指针,如果注入的方式初始化!
    • 最后在需要的地方通过基类指针TaxStrategy调用对应的不同国家的方法。
    • 核心点主要有几地方:
      • 所有国家的税收计算类都继承基类,并且实现基类的抽象方法
      • 在需要使用的地方定义基类对象的指针,通过注入的方式传入需要的子类对象(多态)
      • 最后调用方法通过虚函数表来调用实际传入对象的计算方法(动态绑定、晚绑定)
      • 策略模式提倡的互相替换在这里通过多态来实现,替换体现在实际传入初始化的对象到底是哪一个!
  • 这样做的好处:
    • 如果需要增加新的国家,可以看到大部分代码都是不用修改的,只需要扩展新的类即可
    • 性能的优化,实际说在使用的过程中只需要把需要的对象new出来即可
class TaxStrategy {
public:
    virtual double calculateTax() = 0;
    virtual ~TaxStrategy();
};

class CNTax: public TaxStrategy{
public:
    double calculateTax() override {
        // 国内税计算
    }
};

class USTax: public TaxStrategy{
public:
    double calculateTax() override {
        // 美国税计算
    }
};

class DETax: public TaxStrategy{
public:
    double calculateTax() override {
        // 德国税计算
    }
};
class JPTax: public TaxStrategy{
public:
    double calculateTax() override {
        // 日本税计算
    }
};

class SalesOrder{
private:
    TaxStrategy *taxStrategy;               // 基类指针
public:
    SalesOrder(TaxStrategy *_taxStrategy): taxStrategy(_taxStrategy){

    }
    virtual ~SalesOrder(){
        delete taxStrategy;
        taxStrategy = nullptr;
    }
    double calculate(){
        // ...
        // 还是动态绑定通过虚函数来调用实际的传入对象的calculateTax方法
        double val = taxStrategy->calculateTax();
        // ...
        return val;
    }
};

在这里插入图片描述

通过这个UML图可以看到TaxStrategy和SalesOrder是相对稳定的,而不稳定的是TaxStrategy的子类

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

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

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

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

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

相关文章

pinia 的介绍和使用

pinia是vue2,vue2 尤其是vue3官方推荐的状态管理器,和vuex类似,但使用起来更为简单, 概念: state:定义响应式共享变量 getter:相当于计算属性 actions:相当于方法 npm安装 npm install pinia创建pinia ,注…

【Python】常见容器

Python容器 列表元组字符串集合字典 列表 定义方法:[元素1, 元素2, …] 列表一次可以存储多个不同数据类型的数据,支持嵌套。 例如: list1 ["张三", 33, True] print(list1) print(type(list1))list2 [list, "李四", …

企业数据资产评估的财报显性化及数据资产入表的主要应用场景

一、背景 近年来,企业“数据资产”的概念不断受政府/企业重视和建设.根据《数据资产评估指导意见》规定,数据资产评估是指资产评估机构及其资产评估专业人员遵守法律、行政法规和资产评估准则,根据委托对评估基准日特定目的下的数据资产价值…

Halcon的HWindowControl控件在C#WinForm中的使用介绍(包括绘制ROI)

Halcon的HSmartWindowControl控件在C#WinForm中的使用介绍(包括绘制ROI) 文章目录 Halcon的HSmartWindowControl控件在C#WinForm中的使用介绍(包括绘制ROI)一、 引入hSmartWindowControl控件二、 编写打开图像功能三、 编写绘制RO…

【热门话题】Stable Diffusion:本地部署教程

🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 ​💫个人格言: "如无必要,勿增实体" 文章目录 Stable Diffusion:本地部署教程一、引言二、环境准备1. 硬件配置2. …

Java多态练习2

设计金融产品类Financial,属性包括产品名称、产品介绍、起投金额、产品期限(int)、年化收益(百分数);方法包括发布、截止、投资。 设计金融产品类子类: 基金产品Fund,继承金融产品类…

【JAVASE】带你了解面向对象三大特性之一(继承)

✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:再无B~U~G-CSDN博客 1.继承 1.1 为什么需要继承 Java 中使用类对现实世界中实体来…

牛客网BC-125 序列中整数去重复(难题讲解)

题目如下 --------------------------------------------------------------------------------------------------------------------------------- 题目讲解(思路) -------------------------------------------------------------------------------…

爱上数据结构:二叉树的基本概念

​ ​ 🔥个人主页:guoguoqiang. 🔥专栏:数据结构 ​ 一、树的基本概念 1.概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是因 为它看起…

机器学习 - multi-class 数据集训练 (含代码)

直接上代码 # Multi-class datasetimport numpy as np RANDOM_SEED 42 np.random.seed(RANDOM_SEED) N 100 # number of points per class D 2 # dimensionality K 3 # number of classes X np.zeros((N*K, D)) y np.zeros(N*K, dtypeuint8) for j in range(K):ix rang…

cJSON(API的详细使用教程)

我们今天来学习一般嵌入式的必备库,JSON库 1,json和cJSON 那什么是JSON什么是cJSON,他们之间有什么样的关联呢,让我们一起来探究一下吧。 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式&…

tomcat 结构目录

bin 启动,关闭和其他脚本。这些 .sh文件(对于Unix系统)是这些.bat文件的功能副本(对于Windows系统)。由于Win32命令行缺少某些功能,因此此处包含一些其他文件。比如说:windows下启动tomcat用的是…

物理层习题及其相关知识(谁看谁不迷糊呢)

1. 对于带宽为50k Hz的信道,若有4种不同的物理状态来表示数据,信噪比为20dB 。(1) 按奈奎斯特定理,信道的最大传输数据速率是多少?(2) 按香农定理,信道的最大传输数据速度…

JAVAEE之Spring Boot日志

1. 日志概述 1.1 学习日志的原因 ⽇志对我们来说并不陌生, 从JavaSE部分, 我们就在使用 System.out.print 来打印日志了. 通过打印日志来发现和定位问题, 或者根据日志来分析程序的运行过程. 在Spring的学习中, 也经常根据控制台的日志来分析和定位问题. 随着项⽬的复杂…

记录Linux系统中vim同时开多个窗口编辑文件

在使用Linux进行文本编辑的时候,通常使用vim编辑器编辑文件,当然啦,vim也可以创建文件,如果只是一个一个创建,只需要vim创建即可,但是如何一次性打开多个窗口编辑呢? 目录 1、目标:…

微信小程序uniapp+vue.js旅游攻略系统9krxx

实现了一个完整的旅游攻略小程序系统,其中主要有用户模块、用户表模块、token表模块、收藏表模块、视频信息模块、视频类型模块、景点资讯模块、门票购买模块、旅游攻略模块、景点信息模块、论坛表模块、视频信息评论表模块、旅游攻略评论表模块、景点信息评论表模块…

python 02字符串

字符串可能是用到最多的数据类型了,所有标准序列操作(索引、切片、乘法、成员资格检查、长度、最小值和最大值)都适用于字符串 但别忘了字符串是不可变的,因此所有的元素赋值和切片赋值都是非法的。 1.居中效果 默认为空格 可…

搭建电商购物独立站抓取主流电商产品数据的方法:工具+电商数据采集API接口

分享一个抓取数据产品的方法,也是别人给我说的。 想做一个联盟产品相关的网站,然后需要采集电商网站的产品。咨询大佬告诉我,大量级电商商品数据的采集可以接入专业的电商数据采集API接口,也可以用webscrsper,于是乎就…

【Linux】环境基础开发工具使用——vim使用

Linux 软件包管理器 yum 什么是软件包 1.在 Linux 下安装软件 , 一个通常的办法是下载到程序的源代码 , 并进行编译 , 得到可执行程序 . 2.但是这样太麻烦了 , 于是有些人把一些常用的软件提前编译好 , 做成软件包 ( 可以理解成 windows 上的安装程序) 放在一个服务器…

LangChain - Retrieval

LangChain - Retrieval 文章目录 LangChain - Retrieval文件装载机 Document loaders文本分割 Text Splitting文本嵌入模型 Text embedding models向量存储Retrievers索引 APIClassesFunctions 官方文档:https://python.langchain.com/docs/modules/data_connection…