参考:
策略设计模式 (refactoringguru.cn)
[5. 策略模式 — Graphic Design Patterns (design-patterns.readthedocs.io)](https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/state.html)
[design-patterns-cpp/Strategy.cpp at master · JakubVojvoda/design-patterns-cpp · GitHub](https://github.com/JakubVojvoda/design-patterns-cpp/blob/master/state/State.cpp)
文章目录
- 一、什么是策略模式?
- 二、实现
- 三、优缺点
- 优点
- 缺点
- 四、适用环境
- 五、策略模式与状态模式的区别
一、什么是策略模式?
完成一项任务,往往可以有多种不同的方式,每一种方式称为一个策略,我们可以根据环境或者条件的不同选择不同的策略来完成该项任务。
策略模式定义:策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,让它们可以相互替换。
假如你需要前往机场。你可以选择乘坐公共汽车、预约出租车或骑自行车。这些就是你的出行策略。你可以根据预算或时间等因素来选择其中一种策略。
二、实现
策略(State)模式包含以下主要角色:
1、上下文(Context):也称为环境类,维护指向具体策略的引用, 且仅通过策略接口与该对象进行交流。
2、策略(Strategy):是所有具体策略的通用接口, 它声明了一个上下文用于执行策略的方法。
3、具体策略(Concrete Strategy):实现了上下文所用算法的各种不同变体。
/*
* C++ Design Patterns: Strategy
* Author: Jakub Vojvoda [github.com/JakubVojvoda]
* 2016
*
* Source code is licensed under MIT License
* (for more details see LICENSE)
*
*/
#include <iostream>
/*
* Strategy
* declares an interface common to all supported algorithms
*/
class Strategy
{
public:
virtual ~Strategy() { /* ... */ }
virtual void algorithmInterface() = 0;
// ...
};
/*
* Concrete Strategies
* implement the algorithm using the Strategy interface
*/
class ConcreteStrategyA : public Strategy
{
public:
~ConcreteStrategyA() { /* ... */ }
void algorithmInterface()
{
std::cout << "Concrete Strategy A" << std::endl;
}
// ...
};
class ConcreteStrategyB : public Strategy
{
public:
~ConcreteStrategyB() { /* ... */ }
void algorithmInterface()
{
std::cout << "Concrete Strategy B" << std::endl;
}
// ...
};
class ConcreteStrategyC : public Strategy
{
public:
~ConcreteStrategyC() { /* ... */ }
void algorithmInterface()
{
std::cout << "Concrete Strategy C" << std::endl;
}
// ...
};
/*
* Context
* maintains a reference to a Strategy object
*/
class Context
{
public:
Context( Strategy* const s ) : strategy( s ) {}
~Context()
{
delete strategy;
}
void contextInterface()
{
strategy->algorithmInterface();
}
// ...
private:
Strategy *strategy;
// ...
};
int main()
{
Context context( new ConcreteStrategyA() );
context.contextInterface();
return 0;
}
三、优缺点
优点
- 你可以在运行时切换对象内的算法。
- 你可以将算法的实现和使用算法的代码隔离开来。
- 开闭原则。 你无需对上下文进行修改就能够引入新的策略。
缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。
四、适用环境
- 当你想使用对象中各种不同的算法变体,并希望能在运行时切换算法时,可使用策略模式。
- 当你有许多仅在执行某些行为时略有不同的相似类时,可使用策略模式。
- 如果算法在上下文的逻辑中不是特别重要, 使用该模式能将类的业务逻辑与其算法实现细节隔离开来。
- 当类中使用了复杂条件运算符以在同一算法的不同变体中切换时,可使用该模式。
五、策略模式与状态模式的区别
- 可以通过环境类状态的个数来决定是使用策略模式还是状态模式。
- 使用策略模式时,客户端需要知道所选的具体策略是哪一个,而使用状态模式时,客户端无须关心具体状态,环境类的状态会根据用户的操作自动转换。
- 如果系统中某个类的对象存在多种状态,不同状态下行为有差异,而且这些状态之间可以发生转换时使用状态模式;如果系统中某个类的某一行为存在多种实现方式,而且这些实现方式可以互换时使用策略模式。
- 状态可被视为策略的扩展。两者都基于组合机制:它们都通过将部分工作委派给
帮手
对象来改变其在不同情景下的行为。 策略使得这些对象相互之间完全独立,它们不知道其他对象的存在。但状态模式没有限制具体状态之间的依赖,且允许它们自行改变在不同情景下的状态。