设计模式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;
}

对比分析

  • 正例(策略模式)

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

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

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

相关推荐
七月丶4 小时前
别再手动凑 PR 了:这个 AI Skill 会按仓库习惯自动建分支、拆提交、提 PR
人工智能·设计模式·程序员
刀法如飞4 小时前
从程序员到架构师:6大编程范式全解析与实践对比
设计模式·系统架构·编程范式
九狼4 小时前
Flutter + Riverpod +MVI 架构下的现代状态管理
设计模式
静水流深_沧海一粟21 小时前
04 | 别再写几十个参数的构造函数了——建造者模式
设计模式
StarkCoder21 小时前
从UIKit到SwiftUI的迁移感悟:数据驱动的革命
设计模式
阿星AI工作室1 天前
给openclaw龙虾造了间像素办公室!实时看它写代码、摸鱼、修bug、写日报,太可爱了吧!
前端·人工智能·设计模式
_哆啦A梦2 天前
Vibe Coding 全栈专业名词清单|设计模式·基础篇(创建型+结构型核心名词)
前端·设计模式·vibecoding
阿闽ooo5 天前
中介者模式打造多人聊天室系统
c++·设计模式·中介者模式
小米4965 天前
js设计模式 --- 工厂模式
设计模式
头发还在的女程序员5 天前
【免费下载】企业能源管理系统
小程序·策略模式·能源管理