设计模式之策略模式

什么是策略模式?

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

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

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


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

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

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

相关推荐
lqqjuly2 小时前
设计模式:理论、架构与 C++ 实现—SOLID原则到23 种经典模式
c++·设计模式·架构
Java_2017_csdn6 小时前
Java 策略模式(Strategy Pattern)-(二)
java·开发语言·策略模式
Java_2017_csdn6 小时前
Java 策略模式(Strategy Pattern)-(一)
java·开发语言·策略模式
老码观察7 小时前
设计模式实战解读(九):责任链模式——流水线上层层把关的艺术
java·设计模式·责任链模式
拾光Ծ8 小时前
【Linux系统编程】线程池项目实战与基于策略模式的日志系统
linux·bash·线程池·策略模式·日志
星原望野1 天前
JAVA:策略模式的实战使用
java·开发语言·策略模式
前端张三1 天前
从零构建大模型(零)——搭建配置环境
策略模式
j_xxx404_1 天前
Linux 线程日志系统设计:从策略模式、RAII 到 pthread 线程安全与内核写入路径|附源码
linux·运维·服务器·开发语言·c++·人工智能·策略模式
workflower2 天前
具身智能研究对象:物理交互中的智能行为
设计模式·动态规划·软件工程·软件构建·scrum
折哥的程序人生 · 物流技术专研2 天前
Java 23 种设计模式:从踩坑到精通 | 抽象工厂 —— 支付/收款如何成套创建?跨平台 UI 如何一键换肤?
java·开发语言·后端·设计模式