为什么要用策略模式
最近在写代码的时候因为不同的前提条件,从而执行不同的代码。另外这些前提条件也会因为依赖的原因出现大量嵌套if,从而导致代码从视觉上非常囊肿。
另一个原因是过多的if else会导致代码运行的效率下降。由于CPU分支预测功能的机制,过多过深的if else会极大地降低分支预测成功率,导致运算性能下降。关于这一点可以参考"聊一聊分支预测,思考为什么使用 if/else 语句会降低程序效率”这篇文章。
注意,如果超过四种策略模式,建议使用混合模式。
UML
- Context(环境类):内部维护一个Strategy的对象,面向user提供接口
- Strategy(策略类):提供
- Case(策略):具体的策略实现
代码实现
#include <iostream>
#include <memory>
class Strategy {
public:
Strategy() = default;
virtual ~Strategy() = default;
virtual void execute(double a, double b) = 0;
};
// * Add
class ConcreteStrategyAdd : public Strategy {
public:
ConcreteStrategyAdd() = default;
~ConcreteStrategyAdd() override = default;
void execute(double a, double b) override { std::cout << a + b << std::endl; }
};
// * Subtract
class ConcreteStrategySubtract : public Strategy {
public:
ConcreteStrategySubtract() = default;
~ConcreteStrategySubtract() override = default;
void execute(double a, double b) override { std::cout << a - b << std::endl; }
};
// * Multiply
class ConcreteStrategyMultiply : public Strategy {
public:
ConcreteStrategyMultiply() = default;
~ConcreteStrategyMultiply() override = default;
void execute(double a, double b) override { std::cout << a * b << std::endl; }
};
// * Divide
class ConcreteStrategyDivide : public Strategy {
public:
ConcreteStrategyDivide() = default;
~ConcreteStrategyDivide() override = default;
void execute(double a, double b) override { std::cout << a / b << std::endl; }
};
class Context {
public:
Context(std::unique_ptr<Strategy> strategy)
: strategy_(std::move(strategy)) {}
void ContextInterface(double a, double b) { strategy_->execute(a, b); }
private:
std::unique_ptr<Strategy> strategy_;
};
int main(int argc, char** argv) {
Context context(std::make_unique<ConcreteStrategyAdd>());
context.ContextInterface(1, 2);
context = Context(std::make_unique<ConcreteStrategySubtract>());
context.ContextInterface(1, 2);
context = Context(std::make_unique<ConcreteStrategyMultiply>());
context.ContextInterface(1, 2);
context = Context(std::make_unique<ConcreteStrategyDivide>());
context.ContextInterface(1, 2);
return 0;
}
讨论
以上的内容主要出自网上的策略模式的教程,但是并没有完全解决我面对的烦恼。我一开始想用策略模式,是为了解决if else的判断问题。比如根据一个物体长度的范围,用不同的计算方法,比如物体<10m用方法A,>=10m用方法B。但是策略模式好像只是将不同的策略进行封装,定义统一的接口,我依然还需要用if else
swtich case
来进行判断。