惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - wjwdive

如何使用git submodule拆分大的git项目 MAC多github账号配置步骤 - wjwdive 记录一次flutter boost5.0.2示例调试的过程 【算法】可获得的最大点数问题 使用1panel一键建站 关于混合加密(AES+RSA) C++设计模式汇总 设计模式C++005__桥模式 设计模式C++007__抽象工厂方法模式 设计模式C++004__装饰器模式 设计模式C++003__观察者模式 设计模式C++001__模板方法 使用bundler自动化构建Xcode项目时遇到的问题。 - wjwdive AI图片生成网站 suno AI编曲创作利器 iOS组件化开发之私有库 iOS、Android获取apk公钥MD5信息 阿里图标库批量下载iOS适配的图标 C语言实现回调函数标准方式 - wjwdive swift 自定义tabbar为基本结构的项目 swift 可选类型
设计模式C++002__策略模式
wjwdive · 2024-07-25 · via 博客园 - wjwdive

设计模式C++002__策略模式

1、动机:

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

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

2、策略模式:

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

例如跨国电商公司,订单计算税费的功能。
前期只有3个国家的业务,就只定义3个算法,使用枚举类区分。如果要在新的国家扩展业务。改动代码出如下,枚举定义处要改,还要在订单类里添加新的计算方法。
违反了开闭原则。

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){  //更改
			//...
		}

        //....
     }
    
};

如果使用策略模式,定义一个税费计算抽象基类,基类中只有一个计算税费的虚方法,不同国家的税费计算方法继承自抽象基类,各自实现自己的税费计算方法。
如果要支持新的税费计算方法,只需新建一个子类,根据实际情况实现即可。调用时利用C++的多态性质,在主函数中父类的指针指向子类对象,再用指针调用计算税费方法。
理论上,只要是if-else, switch-case 中可能会扩展新的分支以支持业务。都可以改为策略模式。

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:
    TaxStrategy* strategy;  //这里声明一个虚基类指针,访问类型为private

public:
    SalesOrder(StrategyFactory* strategyFactory){
        this->strategy = strategyFactory->New Strategy();//这里就是子类实例对象的产生的地方,可能是一个工厂方法产生的。
    }
    ~SalesOrder(){
        delete this->strategy;
    }

    public double CalculateTax(){
        //...
        Context context();
        
        double val = 
            strategy->Calculate(context); //多态调用
        //...
    }
    
};

3、策略模式相比 if-else这种分支处理。可以在不改变原有类的基础上,只新增子类,就可以实现对原有功能的扩展。符合开闭原则。

实际上,这也是利用了晚绑定的原理,调用哪一种方法。
结构:

4、要点总结:

  • Strategy及其子类为组提供了一些列可重用的算法,从而使得类型在运行时方便的根据需要再各个算法之间进行切换。
  • Strategy模式同了用条件判断语句以外的一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。
  • 如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销。