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

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对象,从而节省对象开销。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【QT入门】 Qt代码创建布局综合运用:仿写腾讯会议登陆界面

往期回顾: 【QT入门】 Qt代码创建布局之水平布局、竖直布局详解-CSDN博客 【QT入门】 Qt代码创建布局之栅格布局详解-CSDN博客 【QT入门】 Qt代码创建布局之分裂器布局详解-CSDN博客 【QT入门】 Qt代码创建布局综合运用:仿写腾讯会议登陆界面 一、界面分…

YOLO V8-Detection 【单张图片】 推理详解及部署实现

前言 在实际处理过程中,我们使用YOLO V8进行推理时,通常会针对一张图片进行推理。如果需要对多张图片进行推理,则可以通过一个循环来实现对图片逐张进行推理。 单张图片推理时,需要注意图片的尺寸必须是32的倍数,否则…

【氮化镓】缓冲层结构对GaN HEMT射频性能的影响

【Effect of different layer structures on the RF performance of GaN HEMT devices】 研究总结: 本研究探讨了不同缓冲层结构对氮化镓高电子迁移率晶体管(GaN HEMT)射频性能的影响。通过对比三种不同缓冲层结构的GaN HEMT设备&#xff0…

海外问卷调查项目拆解(操作全流程演示)保姆级攻略具体操作

海外问卷调查是怎么做的?好做吗? 关于这个问题,不管我说好做、或者不好做,都并不能解决问题; 所以,这篇文章直接把做题的全过程展现给你看,你自己去真实地感受一下,这个玩意儿到底…

【电商API数据采集接口接入】如何搭建电商数据指标体系?

01 什么是好的数据指标? 电商商品数据采集API接口接入 01 前言 做数据分析的工作已经将近6年了,形形色色的业务方也合作了不少。大部分业务方都给我一个感觉就是我什么数据指标都要看,越多越多好,即使看了这些指标之后什么事…

智慧开发平台免!费!申请试用

原创 F学社 F学社 2024-04-01 17:13 江苏 扫描二维码即可申请试用 01 智慧开发平台简介 F1 WIFI智慧教育平台是可支持线上线下联动的基于FPGA的口袋式数字系统学习平台。其采用了AMD、Altera、安路、高云等国外国内主流公司的FPGA进行数字系统方向的教学实验设计&#xff0c…

【力扣刷题日记】1421.净现值查询

前言 练习sql语句,所有题目来自于力扣(https://leetcode.cn/problemset/database/)的免费数据库练习题。 今日题目: 1421.净现值查询 表:NPV 列名类型idintyearintnpvint (id, year) 是该表主键(具有唯一值的列的…

策略模式图

策略模式 小小的图解 主要的三个角色 Strategy—抽象策略角色ConcreateStrategy—具体策略角色Context—上下文角色 封装了对具体策略的调用可以使用set的依赖注入也可以使用构造方法 核心是上下文角色 只要调用上下文角色就行,实现解耦 策略 工厂 将上下文角…

【滑动窗口】Leetcode 最小覆盖子串

题目解析 76. 最小覆盖子串 本题将意思转换一下:寻找最小可重复字符的字串 算法讲解 使用滑动窗口哈希表,进行入窗口->判断哈希表中的元素是否符合最小可重复子串的条件->出窗口 class Solution { public://检查两个hash表中的字符bool check…

【快捷部署】011_PostgreSQL(16)

📣【快捷部署系列】011期信息 编号选型版本操作系统部署形式部署模式复检时间011PostgreSQL16Ubuntu 20.04Docker单机2024-03-28 一、快捷部署 #!/bin/bash ################################################################################# # 作者&#xff1…

leetcode代码记录(买卖股票的最佳时机

目录 1. 题目:2. 我的代码:小结: 1. 题目: 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股…

动物造句子

动物造句子 附小看重家校互动,有时候会邀请各行各业的家长到班里讲课。德德上小学二年级时,有一次,班主任提出邀请我去讲课。 我那时候只给研究生讲一门课《信息论》,这是一门对于研究生来说都比较抽象的课。我怎么把信息论的内…

让ECC升级S/4HANA一步到位的“全面升级方案包”

SAP最新一代商务套件S/4HANA比ECC系统拥有更高性能的存储数据库HANA、更个性化的Fiori用户界面设计系统,能够大大提升系统效率,带来便捷、高效、良好的用户体验。但企业原先使用的ECC系统里面保存了积累多年的关键流程和数据,让企业面对系统升…

力扣爆刷第111天之CodeTop100五连刷41-45

力扣爆刷第111天之CodeTop100五连刷41-45 文章目录 力扣爆刷第111天之CodeTop100五连刷41-45一、232. 用栈实现队列二、4. 寻找两个正序数组的中位数三、31. 下一个排列四、69. x 的平方根五、8. 字符串转换整数 (atoi) 一、232. 用栈实现队列 题目链接:https://le…

Android 代码自定义drawble文件实现View圆角背景

简介 相信大多数Android开发都会遇到一个场景,给TextView或Button添加背景颜色,修改圆角,描边等需求。一看到这样的实现效果,自然就是创建drawble文件,设置相关属性shap,color,radius等。然后将…

观察者模式 C++

👂 Honey Honey - 孙燕姿 - 单曲 - 网易云音乐 目录 🌼前言 🌼描述 🎂问题 💪解决方案 🈲现实场景 代码 场景1 -- 报纸发行 场景 解释 代码 场景2 -- 气象资料发布 场景3 -- 过红绿灯 &#x…

渗透测试:数据库UDF提权(linux)

目录 开头: 1.UDF提权简介: 1.1共享库文件(UDF文件)指定目录: 版本特征: 操作系统版本: 2.靶场UDF提权复现 提权前提 1.要有一个高权限的MySQL的账号 ​编辑 2.MySQL的权限配置secure_file_priv为空 3.必须有存放UDF文件的…

nginx详细配置,高可用

Nginx是一款高性能的Web服务器和反向代理服务器,通常用来进行负载均衡,提供高可用的服务。而Keepalived是一款开源的高可用性解决方案,可以提高系统的可靠性和稳定性。使用Nginx和Keepalived来配置高可用服务的具体步骤如下:1. 安…

题库管理系统-基于Springboot实现JAVA+SQL离散数学题库管理系统(完整源码+LW+翻译)

基于Springboot实现JAVASQL离散数学题库管理系统(完整源码LW翻译) 概述: 本系统具体完成的功能如下: 1题库的管理与维护:新题的录入,修改,删除等功能。 2生成试卷:包括自动生成与手工改动,要…

vue创建项目下载动态路由v-for mounted websocket :style :class store使用说明

在Vue中创建一个项目,并整合动态路由、v-for、mounted生命周期钩子、WebSocket、:style、:class以及Vuex的store,涉及到多个Vue核心特性的使用。下面我将简要说明如何逐步整合这些特性。 1. 创建Vue项目 使用Vue CLI创建项目: 2. 配置动态路…