设计模式之策略模式

什么是策略模式?

策略模式 是一种行为型设计模式,它让你能在运行时 动态地改变对象的行为

它的核心思想是:把算法(或行为)封装成独立的类,让它们可以互相替换

比如:一个游戏角色可以有多种攻击方式(近战、远程、魔法),你希望在游戏运行时切换攻击方式,而不是写死在代码里。


🚫 不使用策略模式的写法(硬编码)

假设我们要实现一个"鸭子"类,不同鸭子有不同的飞行方式。

复制代码
// 不使用策略模式
#include <iostream>
using namespace std;

class Duck {
public:
    void quack() {
        cout << "嘎嘎叫" << endl;
    }

    // 飞行方式被写死在类里
    virtual void fly() {
        cout << "用翅膀飞" << endl;
    }
};

class RubberDuck : public Duck {
public:
    // 橡皮鸭不会飞!
    void fly() override {
        cout << "我不会飞 😢" << endl;
    }
};

class MallardDuck : public Duck {
    // 绿头鸭正常飞
};

int main() {
    Duck* d1 = new MallardDuck();
    Duck* d2 = new RubberDuck();

    d1->fly(); // 输出:用翅膀飞
    d2->fly(); // 输出:我不会飞 😢

    delete d1;
    delete d2;
    return 0;
}

❌ 缺点:

  1. 代码重复 :如果有一百种鸭子,每种飞法不同,就要写一百个 fly()
  2. 难以复用:比如"火箭推进飞行"只能在一个鸭子里用,不能共享给其他需要火箭飞的角色(比如机器人)。
  3. 违反开闭原则:想加新飞行方式?必须修改或继承 Duck 类,容易出错。

✅ 使用策略模式的写法

我们把"飞行行为"抽出来,变成独立的接口(抽象类),然后让不同飞行方式实现它。

复制代码
#include <iostream>
using namespace std;

// ========= 策略接口 =========
class FlyBehavior {
public:
    virtual ~FlyBehavior() = default;
    virtual void fly() = 0;
};

// ========= 具体策略 =========
class FlyWithWings : public FlyBehavior {
public:
    void fly() override {
        cout << "用翅膀飞 🕊️" << endl;
    }
};

class FlyNoWay : public FlyBehavior {
public:
    void fly() override {
        cout << "我不会飞 😢" << endl;
    }
};

class FlyWithRocket : public FlyBehavior {
public:
    void fly() override {
        cout << "用火箭飞 🚀" << endl;
    }
};

// ========= 上下文(Duck) =========
class Duck {
protected:
    FlyBehavior* flyBehavior; // 指向策略的指针

public:
    Duck(FlyBehavior* fb) : flyBehavior(fb) {}

    void setFlyBehavior(FlyBehavior* fb) {
        flyBehavior = fb; // 运行时可换策略!
    }

    void performFly() {
        flyBehavior->fly(); // 委托给策略
    }

    void quack() {
        cout << "嘎嘎叫" << endl;
    }
};

// 具体鸭子
class MallardDuck : public Duck {
public:
    MallardDuck() : Duck(new FlyWithWings()) {}
};

class RubberDuck : public Duck {
public:
    RubberDuck() : Duck(new FlyNoWay()) {}
};

// 甚至可以给机器人用!
class Robot {
private:
    FlyBehavior* flyBehavior;
public:
    Robot(FlyBehavior* fb) : flyBehavior(fb) {}
    void launch() { flyBehavior->fly(); }
};

// ========= 主函数 =========
int main() {
    Duck* duck1 = new MallardDuck();
    Duck* duck2 = new RubberDuck();

    duck1->performFly(); // 用翅膀飞 🕊️
    duck2->performFly(); // 我不会飞 😢

    // 动态更换策略!
    duck2->setFlyBehavior(new FlyWithRocket());
    duck2->performFly(); // 用火箭飞 🚀

    // 火箭飞行策略还能给机器人用!
    Robot robot(new FlyWithRocket());
    robot.launch(); // 用火箭飞 🚀

    // 注意:这里简化了内存管理,实际建议用智能指针
    delete duck1;
    delete duck2;
    return 0;
}

✅ 使用策略模式的优点

优点 说明
解耦 行为(策略)和主体(Duck)分离,各自独立变化
可复用 同一个飞行策略可以用在鸭子、机器人、飞机等任何地方
易于扩展 加新飞行方式?只需新增一个 FlyBehavior 子类,无需改 Duck
运行时切换 可以在程序运行中动态改变行为(比如游戏中升级武器)
符合开闭原则 对扩展开放,对修改关闭

⚠️ 缺点(也要知道)

  • 类数量增多:每个策略都是一个类,小型项目可能显得"过度设计"。
  • 客户端需了解策略:调用者要知道有哪些策略可用(不过可通过工厂模式缓解)。
  • 内存管理稍复杂 :涉及指针/动态分配(C++ 中建议用 std::unique_ptr 管理)。

🔚 总结一句话:

策略模式 = 把"怎么做"从"谁来做"里抽出来,变成可插拔的模块。

就像你手机的充电线:USB-C、Lightning、Micro USB 是不同的"策略",手机(上下文)只要支持换线,就能适配不同充电方式!

相关推荐
寅时码1 天前
React 正在演变为一场不可逆的赛博瘟疫:AI 投毒、编译器迷信与装死的官方
前端·react.js·设计模式
willow4 天前
Axios由浅入深
设计模式·axios
七月丶6 天前
别再手动凑 PR 了:这个 AI Skill 会按仓库习惯自动建分支、拆提交、提 PR
人工智能·设计模式·程序员
刀法如飞6 天前
从程序员到架构师:6大编程范式全解析与实践对比
设计模式·系统架构·编程范式
九狼6 天前
Flutter + Riverpod +MVI 架构下的现代状态管理
设计模式
静水流深_沧海一粟7 天前
04 | 别再写几十个参数的构造函数了——建造者模式
设计模式
StarkCoder7 天前
从UIKit到SwiftUI的迁移感悟:数据驱动的革命
设计模式
阿星AI工作室7 天前
给openclaw龙虾造了间像素办公室!实时看它写代码、摸鱼、修bug、写日报,太可爱了吧!
前端·人工智能·设计模式
_哆啦A梦8 天前
Vibe Coding 全栈专业名词清单|设计模式·基础篇(创建型+结构型核心名词)
前端·设计模式·vibecoding