设计模式5-策略模式(Strategy)

设计模式5-策略模式

简介

策略模式也是属于组件协作 模式一种。现代软件专业分工之后的第一个结果是框架语音应用程序的划分。组建协作模式,通过晚期绑定来实现框架与应用程序之间的松耦合。组件协作是二者之间协作时常用的模式。

目的

在软件构建过程中,某些对象使用的算法可能多种多样。会经常改动。如果将这些算法都编码到对象中,将会使对象变得异常复杂。而且有时候不支持使用的算法也是一个性能负担。如何在运行时根据需要透明的更改对象的算法?将算法与对象本身上进行解耦。策略模式的目的就是避免上述问题。

定义

程序中定义一系列算法。把他们一个个封装起来。并且使他们可互相替换变化该模式使得算法可独立于使用它的客户程序而变化扩展或者进行子类化。

结构

策略模式的结构

策略模式包含以下几个部分:

  1. 策略接口(Strategy Interface):定义所有支持的算法的接口。
  2. 具体策略类(Concrete Strategy Classes):实现策略接口的具体算法。
  3. 上下文类(Context Class):包含一个策略对象的引用,并提供设置和执行策略的方法。

要点

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

举例说明

策略模式(Strategy Pattern)是一种行为设计模式,定义了算法族,并将每个算法封装起来,使它们可以互换。策略模式让算法的变化不会影响到使用算法的客户。

1. 策略接口

cpp 复制代码
class Strategy {
public:
    virtual ~Strategy() {}
    virtual void execute() const = 0;
};

2. 具体策略类

cpp 复制代码
class ConcreteStrategyA : public Strategy {
public:
    void execute() const override {
        std::cout << "ConcreteStrategyA executed" << std::endl;
    }
};

class ConcreteStrategyB : public Strategy {
public:
    void execute() const override {
        std::cout << "ConcreteStrategyB executed" << std::endl;
    }
};

3. 上下文类

cpp 复制代码
class Context {
private:
    Strategy* strategy;

public:
    Context(Strategy* strategy = nullptr) : strategy(strategy) {}

    ~Context() {
        delete strategy;
    }

    void setStrategy(Strategy* newStrategy) {
        delete strategy;
        strategy = newStrategy;
    }

    void executeStrategy() const {
        if (strategy) {
            strategy->execute();
        } else {
            std::cout << "No strategy set" << std::endl;
        }
    }
};

4. 客户端代码

cpp 复制代码
int main() {
    Context context;

    context.setStrategy(new ConcreteStrategyA());
    context.executeStrategy();

    context.setStrategy(new ConcreteStrategyB());
    context.executeStrategy();

    return 0;
}

策略模式的反例

反例展示了没有使用策略模式时的代码,这样的代码往往存在代码重复、维护困难、扩展不便的问题。

没有使用策略模式的代码

cpp 复制代码
class Context {
public:
    enum StrategyType {
        STRATEGY_A,
        STRATEGY_B
    };

    void executeStrategy(StrategyType type) const {
        switch (type) {
        case STRATEGY_A:
            std::cout << "Strategy A executed" << std::endl;
            break;
        case STRATEGY_B:
            std::cout << "Strategy B executed" << std::endl;
            break;
        default:
            std::cout << "No valid strategy selected" << std::endl;
            break;
        }
    }
};

int main() {
    Context context;
    context.executeStrategy(Context::STRATEGY_A);
    context.executeStrategy(Context::STRATEGY_B);

    return 0;
}

对比分析

  • 正例(策略模式)

    • 可扩展性:可以轻松地添加新策略,而无需修改上下文类。
    • 可维护性:每个策略封装在独立的类中,代码更易读、更易维护。
    • 开闭原则:对扩展开放,对修改关闭。
  • 反例(未使用策略模式)

    • 可扩展性差:添加新策略需要修改上下文类的代码。
    • 可维护性差:所有策略代码集中在一个类中,代码量大,维护困难。
    • 违背开闭原则:每次添加新策略都需要修改上下文类,容易引入新的错误。

通过策略模式,代码的灵活性和可维护性显著提高,可以轻松地添加、删除或更改策略,而不影响客户端代码。

相关推荐
莫得感情 o6 小时前
设计模式 22 · 三个冷门模式:中介者、访问者、解释器
java·设计模式
AI人工智能+电脑小能手1 天前
大白话说Java设计模式-08-建造者模式(业务实战篇)
java·设计模式·建造者模式·架构设计·对象构建
coding4u1 天前
Mac 外接显示器完全指南:从插上线到调好每个参数
macos·计算机外设·文件管理·显示器·策略模式·quick look扩展
AustinXu1 天前
从 Claude Code 到 Claude Tag,Harness Engineering 走到了组织这一层
设计模式·团队管理
剧中有戏1 天前
单例模式从入门到精通:一个数据库连接池的完整剖析
设计模式
胡萝卜术1 天前
编译期与运行期的双重防线:从 TypeScript 类型之争到 LLM 输出的自动化择优
前端·设计模式·面试
货拉拉技术1 天前
重塑 Agent 度量衡:基于 LLM-as-a-Judge 的离线评估体系与实践
算法·设计模式
KhalilRuan1 天前
设计模式小记
设计模式
卡牌RWA研究院1 天前
Relique:一张精品卡牌如何从收藏品变成可交易的链上资产?
设计模式·金融·区块链·创业创新
剧中有戏2 天前
抽象工厂模式从入门到精通:一个多云存储案例的完整剖析(修订版)
设计模式