【第14节】C++设计模式(行为模式)-Strategy (策略)模式

一、问题的提出

Strategy 模式:算法实现与抽象接口的解耦

Strategy 模式和 Template 模式要解决的问题是相似的,都是为了将业务逻辑(算法)的具体实现与抽象接口解耦。Strategy 模式通过将算法封装到一个类(Context)中,并通过组合的方式将具体算法的实现委托给组合对象来完成。

二、模式选择

Strategy 模式的典型结构如下图所示:

其核心思想是将算法的逻辑抽象接口(如 `DoAction`)封装到一个类中(Context),然后通过委托的方式将具体的算法实现交给具体的 Strategy 类(如 `ConcreteStrategyA` 和 `ConcreteStrategyB`)来完成。

三、代码实现

以下是 Strategy 模式的完整实现代码,采用 C++ 编写。

代码实现

Strategy.h

cpp 复制代码
#ifndef _STRATEGY_H_
#define _STRATEGY_H_

// 抽象策略类,定义算法接口
class Strategy {
public:
    Strategy() {}
    virtual ~Strategy() {}
    virtual void AlgorithmInterface() = 0;  // 算法接口,子类实现
};

// 具体策略类A,实现算法接口
class ConcreteStrategyA : public Strategy {
public:
    ConcreteStrategyA() {}
    virtual ~ConcreteStrategyA() {}
    void AlgorithmInterface() override;  // 实现算法接口
};

// 具体策略类B,实现算法接口
class ConcreteStrategyB : public Strategy {
public:
    ConcreteStrategyB() {}
    virtual ~ConcreteStrategyB() {}
    void AlgorithmInterface() override;  // 实现算法接口
};

#endif //~_STRATEGY_H_

Strategy.cpp

cpp 复制代码
#include "Strategy.h"
#include <iostream>
using namespace std;

// 具体策略类A的算法实现
void ConcreteStrategyA::AlgorithmInterface() {
    cout << "ConcreteStrategyA: AlgorithmInterface" << endl;
}

// 具体策略类B的算法实现
void ConcreteStrategyB::AlgorithmInterface() {
    cout << "ConcreteStrategyB: AlgorithmInterface" << endl;
}

Context.h

cpp 复制代码
#ifndef _CONTEXT_H_
#define _CONTEXT_H_

class Strategy;

/**
 * Context 类是 Strategy 模式的关键,也是 Strategy 模式和 Template 模式的主要区别所在。
 * Strategy 模式通过组合(委托)的方式实现算法的异构,而 Template 模式则通过继承的方式实现。
 */
class Context {
public:
    Context(Strategy* strategy);  // 构造函数,传入具体策略
    ~Context();
    void DoAction();  // 执行策略
private:
    Strategy* _strategy;  // 组合的策略对象
};

#endif //~_CONTEXT_H_

Context.cpp

cpp 复制代码
#include "Context.h"
#include "Strategy.h"
#include <iostream>
using namespace std;

// 构造函数,初始化策略对象
Context::Context(Strategy* strategy) : _strategy(strategy) {}

// 析构函数,释放策略对象
Context::~Context() {
    if (_strategy) {
        delete _strategy;
    }
}

// 执行策略
void Context::DoAction() {
    _strategy->AlgorithmInterface();
}

main.cpp

cpp 复制代码
#include "Context.h"
#include "Strategy.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[]) {
    Strategy* strategyA = new ConcreteStrategyA();  // 创建具体策略A
    Context* contextA = new Context(strategyA);     // 创建上下文,传入策略A
    contextA->DoAction();                          // 执行策略A

    Strategy* strategyB = new ConcreteStrategyB();  // 创建具体策略B
    Context* contextB = new Context(strategyB);     // 创建上下文,传入策略B
    contextB->DoAction();                          // 执行策略B

    delete contextA;
    delete contextB;

    return 0;
}

代码说明

Strategy 模式的实现非常直观,其核心思想是将算法的逻辑封装到一个类中,并通过组合的方式将具体算法的实现委托给组合对象。Context 类通过持有 Strategy 对象的指针,动态调用具体的算法实现。

四、总结讨论

Strategy 模式和 Template 模式解决了类似的问题,但它们采用了不同的实现方式:Strategy 模式通过组合(委托)实现算法的异构,而 Template 模式则通过继承实现。这两种方式各有优缺点:

继承的优缺点

优点:

(1)易于修改和扩展被复用的实现。

缺点:

(1)破坏了封装性,父类的实现细节暴露给子类;

(2)属于"白盒"复用;

(3)当父类的实现更改时,所有子类都需要随之改变;

(4)继承的实现在运行期间不能改变(编译期间已确定)。

组合的优缺点

优点:

(1)属于"黑盒"复用,被包含对象的内部细节对外不可见;

(2)封装性好;

(3)实现和抽象的依赖性小;

(4)可以在运行期间动态定义实现(通过抽象基类的指针)。

缺点:

(1)系统中对象可能过多。

从上述对比可以看出,组合相比继承具有更好的灵活性和封装性。因此,在面向对象设计中,有一条重要的原则:优先使用对象组合,而非类继承(Favor Composition Over Inheritance)。

Strategy 模式通过组合的方式实现了算法与抽象接口的解耦,适用于需要在运行时动态切换算法的场景。与 Template 模式相比,Strategy 模式更加灵活,避免了继承带来的强耦合性。在实际开发中,优先使用组合而非继承,可以显著提高代码的可维护性和扩展性。

相关推荐
闻缺陷则喜何志丹8 分钟前
【排序】P9127 [USACO23FEB] Equal Sum Subarrays G|普及+
c++·算法·排序·洛谷
moringlightyn20 分钟前
c++ 智能指针
开发语言·c++·笔记·c++11·指针·智能指针
Code_Shark23 分钟前
AtCoder Beginner Contest 424 题解
数据结构·c++·算法·数学建模·青少年编程
今天又在学代码写BUG口牙35 分钟前
MFC应用程序,工作线程学习记录
c++·mfc·1024程序员节
j_xxx404_37 分钟前
C++ STL简介:从原理到入门使用指南
开发语言·c++
15Moonlight1 小时前
06-MySQL基础查询
数据库·c++·mysql·1024程序员节
Dream it possible!1 小时前
LeetCode 面试经典 150_链表_反转链表 II(60_92_C++_中等)(头插法)
c++·leetcode·链表·面试
闲人编程1 小时前
Python设计模式实战:用Pythonic的方式实现单例、工厂模式
开发语言·python·单例模式·设计模式·工厂模式·codecapsule·pythonic
十五年专注C++开发2 小时前
Drogon: 一个开源的C++高性能Web框架
linux·c++·windows·后端开发·服务器开发
Dream it possible!3 小时前
LeetCode 面试经典 150_链表_随机链表的复制(59_138_C++_中等)
c++·leetcode·链表