设计模式之策略模式

什么是策略模式?

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

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

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


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

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

复制代码
// 不使用策略模式
#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 是不同的"策略",手机(上下文)只要支持换线,就能适配不同充电方式!

相关推荐
胡志辉的博客3 小时前
多智能体协作,不是多开几个 Agent:从中介者模式看 OpenClaw 和 Hermes Agent
人工智能·设计模式·ai·agent·中介者模式·openclaw·herman
shark22222223 小时前
能懂!基于Springboot的用户增删查改(三层设计模式)
spring boot·后端·设计模式
014-code4 小时前
日志规范:怎么写才不算写废话
java·开发语言·设计模式·日志
楼田莉子5 小时前
同步/异步日志系统:日志落地模块\日志器模块\异步日志模块
linux·服务器·c++·学习·设计模式
kyriewen1112 小时前
代码写成一锅粥?这5种设计模式让你的项目“起死回生”
前端·javascript·设计模式·typescript·ecmascript·html5
kyriewen12 小时前
代码写成一锅粥?这5种设计模式让你的项目“起死回生”
前端·javascript·设计模式
两年半的个人练习生^_^13 小时前
每日一学:设计模式之原型模式
java·开发语言·设计模式·原型模式
断眉的派大星1 天前
工厂模式(Factory Pattern)完整详解
python·设计模式
AI大法师1 天前
复盘 TikTok 品牌升级:动态品牌系统应该怎么理解和落地
大数据·人工智能·设计模式
妙蛙种子3111 天前
【Java设计模式 | 创建者模式】建造者模式
java·开发语言·后端·设计模式·建造者模式