策略模式
模式介绍
- GOF《设计模式:可复用面向对象软件的基础》书中对策略模式描述:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
- 策略模式为了适应不同的需求,封装了变化点,这个变化点就是实现不同需求的算法,但各种算法怎么使用需要客户端知道。
代码实现
- 场景:假设每个人吃饭时只能选定一种食物,食物分为几大类(肉类、蔬菜类、米饭、面条等),每个人可以选择不同的食物。将吃的动作抽象出来,以应对不同的食物选择。
#include <iostream>
#include <memory>
class Strategy {
public:
Strategy() = default;
virtual ~Strategy() = default;
virtual void Eat() = 0;
};
class Meat : public Strategy {
public:
Meat() = default;
~Meat() = default;
virtual void Eat() override { std::cout << "Meat" << std::endl; }
};
class Vegetable : public Strategy {
public:
Vegetable() = default;
~Vegetable() = default;
virtual void Eat() override { std::cout << "Vegetable" << std::endl; }
};
class Rice : public Strategy {
public:
Rice() = default;
~Rice() = default;
virtual void Eat() override { std::cout << "Rice" << std::endl; }
};
class Noodles : public Strategy {
public:
Noodles() = default;
~Noodles() = default;
virtual void Eat() override { std::cout << "Noodles" << std::endl; }
};
// Context将它的客户的请求转发给它的Strategy
class Context {
public:
Context(Strategy *ptr) : m_strategy(ptr) {}
~Context() = default;
void Eat() {
if (m_strategy)
m_strategy->Eat();
}
// 测试添加,实际也可使用工厂模式包装,创建Context对象
void ResetStrategy(Strategy *ptr) { m_strategy = ptr; }
private:
Strategy *m_strategy;
};
int main(int argc, char *argv[]) {
std::shared_ptr<Strategy> meat = std::make_shared<Meat>();
std::shared_ptr<Strategy> vegetable = std::make_shared<Vegetable>();
std::shared_ptr<Strategy> rice = std::make_shared<Rice>();
std::shared_ptr<Strategy> noodles = std::make_shared<Noodles>();
Context context(meat.get());
context.Eat();
context.ResetStrategy(vegetable.get());
context.Eat();
context.ResetStrategy(rice.get());
context.Eat();
context.ResetStrategy(noodles.get());
context.Eat();
return 0;
}
总结
- Strategy类层次为Context类定义了一系列可供重用的算法或行为,客户端通过Context类访问不同的算法或行为。
- 简化单元测试,封装了变化,消除了一些条件语句。
- 客户端必须知道所有的策略类。
- 有时Context会创建和初始化一些永远不会用到的参数,此时就需要更紧密的耦合关系。
起始