news 2026/5/21 14:31:40

深入理解C++之策略模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入理解C++之策略模式

1 会飞的鸭子

Duck 基类,包含两个成员函数 (swim, display);派生类 MallardDuck,RedheadDuck 和 RubberDuck,各自重写继承自基类的 display 成员函数

1

2

3

4

5

6

7

8

9

10

11

12

classDuck {

public:

voidswim();

virtualvoiddisplay();

};

classMallardDuck :publicDuck {

public:

voiddisplay();// adding virtual is OK but not necessary

};

classRedheadDuck ...

现在要求,为鸭子增加会飞的技能 -- fly,那么应该如何设计呢?

1.1 继承

考虑到并非所有的鸭子都会飞,可在 Duck 中加个普通虚函数 fly,则“会飞”的派生类继承 fly 的一个缺省实现,而“不会飞”的派生类重写 fly 的实现

1

2

3

voidDuck::fly() { std::cout <<"I am flying !"<< std::endl; }

voidRubberDuck::fly() { std::cout <<"I cannot fly !"<< std::endl; }

1.2 接口

实际上,使用一般虚函数来实现多态并非良策,在前文 C++11 之 override 关键字中的 “1.2 一般虚函数” 已经有所解释,常用的代替方法是 “纯虚函数 + 缺省实现”,

即将 fly 在基类中声明为纯虚函数,同时写一个缺省实现

因为是纯虚函数,所以只有“接口”会被继承,而缺省的“实现”却不会被继承,是否调用基类里 fly 的缺省实现,则取决于派生类里重写的 fly 函数

1

2

voidMallardDuck::fly() { Duck::fly(); }

voidRedheadDuck::fly() { Duck::fly(); }

1.3 设计模式

到目前为止,并没有使用设计模式,但问题看上去已经被解决了,实际上使用或不使用设计模式,取决于实际需求,也取决于开发者

<Design Patterns> 中,关于策略模式的适用情景,如下所示:

1)many related classes differ only in their behavior

2)you need different variants of an algorithm

3)an algorithm uses data that clients shouldn't know about

4)a class defines many behaviors, and these appear as multiple conditional statements in its operations

显然,鸭子的各个派生类属于 “related classes”,关键就在于“飞”这个行为,如果只是将“飞”的行为,简单划分为“会飞”和“不会飞”,则不使用设计模式完全可以

如果“飞行方式”,随着派生类的增多,至少会有几十种;或者视“飞行方式”为一种算法,以后还会不断改进;再或“飞行方式”作为封装算法,提供给第三方使用。

那么此时,设计模式的价值就体现出来了 -- 易复用,易扩展,易维护。

而第 4) 种适用情景,多见于重构之中 -- "Replace Type Code with State/Strategy"

2 设计原则

在引出策略模式之前,先来看面向对象的三个设计原则

1)隔离变化:identify what varies and separate them from what stays the same

Duck 基类中, 很明显“飞行方式“是变化的,于是把 fly 择出来,和剩余不变的分隔开来

2)编程到接口:program to an interface, not an implementation

分出 fly 之后,将其封装为一个接口,里面实现各种不同的“飞行方式” (一系列”算法“),添加或修改算法都在这个接口里面进行。“接口”对应于 C++ 便是抽象基类,

即将“飞行方式”封装为 FlyBehavior 类,该类中声明 fly 成员函数为纯虚函数

1

2

3

4

5

6

7

8

9

10

11

classFlyBehavior {

public:

virtualvoidfly() = 0;

};

classFlyWithWings :publicFlyBehavior {

public:

virtualvoidfly();

};

classFlyNoWay ...classFlyWithRocket ...

具体实现各种不同的算法 -- “飞行方式”,如下所示:

1

2

3

4

5

voidFlyWithWings::fly() { std::cout <<"I am flying !"<< std::endl; }

voidFlyNoWay::fly() { std::cout <<"I cannot fly !"<< std::endl; }

voidFlyWithRocket::fly() { std::cout <<"I am flying with a rocket !"<< std::endl; }

3)复合 > 继承:favor composition (has-a) over inheritance (is-a)

<Effective C++> 条款 32 中提到,公有继承即是“is-a”,而条款 38 则提及 Composition (复合或组合) 的一个含义是 “has-a”。因此,可以在 Duck 基类中,

声明 FlyBehavior 类型的指针,如此,只需通过指针 _pfB 便可调用相应的”算法“ -- ”飞行方式“

1

2

3

4

5

6

classDuck {

public

...

private:

FlyBehavior* _pfB;// 或 std::shared_ptr<FlyBehavior> _pfB;

};

3 策略模式

3.1 内容

即便不懂设计模式,只有严格按照上面的三个设计原则,则最后的设计思路也会和策略模式类似,可能只是一些细微处的差别

下面来看策略模式的具体内容和结构图:

Defines a family ofalgorithms, encapsulateseach one, and makes theminterchangeable.Strategy lets the algorithm vary independently

from clients that use it.

Context指向Strategy (由指针实现);Context 通过Strategy 接口,调用一系列算法;ConcreteStrategy 则实现了一系列具体的算法

3.2 智能指针上例中,策略模式的“接口” 对应于抽象基类 FlyBehavior,“算法实现”分别对应派生类 FlyWithWings, FlyNoWay, FlyWithRocket,“引用”对应 _pfB 指针

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 14:27:26

智慧铁路列车车辆和人员检测数据集VOC+YOLO格式5059张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件)图片数量(jpg文件个数)&#xff1a;5059标注数量(xml文件个数)&#xff1a;5059标注数量(txt文件个数)&#xff1a;5059标注类别…

作者头像 李华
网站建设 2026/5/21 14:25:46

Steam Deck Tools 终极指南:Windows 掌机的完美伴侣

Steam Deck Tools 终极指南&#xff1a;Windows 掌机的完美伴侣 【免费下载链接】steam-deck-tools (Windows) Steam Deck Tools - Fan, Overlay, Power Control and Steam Controller for Windows 项目地址: https://gitcode.com/gh_mirrors/st/steam-deck-tools 还在为…

作者头像 李华
网站建设 2026/5/21 14:20:06

从零开始将OpenClaw智能体工作流接入Taotoken平台的实践记录

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 从零开始将OpenClaw智能体工作流接入Taotoken平台的实践记录 本文是一份面向开发者的实践指南&#xff0c;旨在清晰演示如何将Open…

作者头像 李华
网站建设 2026/5/21 14:19:57

ElastiFlow网络流量分析系统:从零到企业级监控的架构解密

ElastiFlow网络流量分析系统&#xff1a;从零到企业级监控的架构解密 【免费下载链接】elastiflow Network flow analytics (Netflow, sFlow and IPFIX) with the Elastic Stack 项目地址: https://gitcode.com/gh_mirrors/el/elastiflow 网络流量如同企业的数字血液&am…

作者头像 李华
网站建设 2026/5/21 14:18:56

红队信息收集,总结最全信息收集思路与实操技巧

0x01 简介 无论是做渗透测试还是红队&#xff08;Red Team&#xff09;的工作&#xff0c;信息收集都是工作前期必不可少的一个环节。渗透测试的本质是信息收集&#xff0c;资产信息越多&#xff0c;可攻击面就越广&#xff0c;找到突破口的机会就越大。但随着安全行业的蓬勃发…

作者头像 李华