场景设定
我们先假设有一个 Hero 类,它负责'攻击'这件事。
攻击方式不固定:可以用剑,可以放火球,也可以临时改成空手。问题不在于怎么打,而在于这套行为要不要在运行时换掉。
传统做法:虚函数 + 继承
如果沿着传统 OOP 的路子走,很容易先想到用子类来区分攻击方式。
// 基类
class Hero {
public:
virtual void Attack() {
cout << "空手攻击!" << endl;
}
};
// 派生类:剑士
class Swordsman : public Hero {
public:
void Attack() override {
cout << "挥剑斩击!" << endl;
}
};
// 派生类:法师
class Mage : public Hero {
public:
void Attack() override {
cout << "发射火球!" << endl;
}
};
这种写法能工作,但边界也很明显。
- 对象一旦定型,行为就跟着定型了。
Swordsman还是Swordsman,你不能把一个现成对象直接'切'成Mage。 - 变化一多,子类就开始膨胀。攻击方式如果不是 2 种,而是 20 种、100 种,维护起来会很烦。
它不是不对,只是更适合'类型就是行为'的场景。
用 std::function 把行为拆出来
这里换个思路:Hero 不再决定'怎么打',它只保存一个可调用对象,真正的攻击逻辑由外部注入。
这样 Hero 更像一个壳,攻击方式像一张随时能换的卡。
定义 Hero
#include
;
AttackStrategy = std::function<( Hero&)>;
{
std::cout << << std::endl;
}
{
:
(AttackStrategy strategy = DefaultPunch) : (strategy) {}
{
std::cout << << std::endl;
(*);
std::cout << << std::endl;
}
{
attack_skill = new_strategy;
}
:
AttackStrategy attack_skill;
};

