设计模式之策略模式

什么是策略模式?

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

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

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


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

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

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

相关推荐
驴儿响叮当20103 小时前
设计模式之中介模式
设计模式
驴儿响叮当20106 小时前
设计模式之命令模式
设计模式·命令模式
驴儿响叮当20109 小时前
设计模式之适配器模式
设计模式·适配器模式
HEU_firejef10 小时前
设计模式——代理模式
设计模式·代理模式
Coder_Boy_11 小时前
从单体并发工具类到分布式并发:思想演进与最佳实践(二)
java·spring boot·分布式·微服务·设计模式
geovindu20 小时前
python: Memento Pattern
开发语言·python·设计模式·备忘录模式
HEU_firejef1 天前
设计模式——单例模式
单例模式·设计模式
电子科技圈1 天前
SmartDV与Mirabilis Design宣布就SmartDV IP系统级模型达成战略合作
大数据·设计模式·软件工程
带娃的IT创业者1 天前
解密OpenClaw系列04-OpenClaw设计模式应用
设计模式·软件工程·软件架构·ai agent·ai智能体开发·openclaw