策略模式
策略模式
策略是一种行为设计模式, 它将一组行为转换为对象, 并使其在原始上下文对象内部能够相互替换。原始对象被称为上下文, 它包含指向策略对象的引用并将执行行为的任务分派给策略对象。 为了改变上下文完成其工作的方式, 其他对象可以使用另一个对象来替换当前链接的策略对象。
应用场景
一天, 你打算为游客们创建一款导游程序。 该程序的核心功能是提供美观的地图, 以帮助用户在任何城市中快速定位。用户期待的程序新功能是自动路线规划:他们希望输入地址后就能在地图上看到前往目的地的最快路线。程序的首个版本只能规划公路路线。驾车旅行的人们对此非常满意。 但很显然, 并非所有人都会在度假时开车。 因此你在下次更新时添加了规划步行路线的功能。 此后, 你又添加了规划公共交通路线的功能。而这只是个开始。 不久后, 你又要为骑行者规划路线。又过了一段时间, 你又要为游览城市中的所有景点规划路线。尽管从商业角度来看, 这款应用非常成功, 但其技术部分却让你非常头疼: 每次添加新的路线规划算法后,导游应用中主要类的体积就会增加一倍。 终于在某个时候, 你觉得自己没法继续维护这堆代码了。
解决方案
策略模式建议找出负责用许多不同方式完成特定任务的类, 然后将其中的算法抽取到一组被称为策略的独立类中。
![Title alt text](https://refactoringguru.cn/images/patterns/diagrams/strategy/solution.png?id=0813a174b29a2ed5902d)
在导游应用中, 每个路线规划算法都可被抽取到只有一个 buildRoute生成路线方法的独立类中。 该方法接收起点和终点作为参数, 并返回路线中途点的集合。
结构图
![Title alt text](https://refactoringguru.cn/images/patterns/diagrams/strategy/structure.png?id=c6aa910c94960f35d100)
示例代码
class Strategy
{
public:
virtual ~Strategy() {}
virtual std::string doAlgorithm(const std::vector<std::string>&data)const = 0;
};
/* The context defines the interface of interest to clients*/
class Context
{
private:
Strategy * stragety_;
public:
Context(Strategy *strategy = nullptr) : strategy_(strategy)
{
}
~Context()
{
delete this->strategy_;
}
/**
* Usually, the Context allows replacing a Strategy object at runtime.
*/
void set_strategy(Strategy *strategy)
{
delete this->strategy_;
this->strategy_ = strategy;
}
/**
* The Context delegates some work to the Strategy object instead of
* implementing +multiple versions of the algorithm on its own.
*/
void DoSomeBusinessLogic() const
{
// ...
std::cout << "Context: Sorting data using the strategy (not sure how it'll do it)\n";
std::string result = this->strategy_->DoAlgorithm(std::vector<std::string>{"a", "e", "c", "b", "d"});
std::cout << result << "\n";
// ...
}
};
class ConcreteStrategyA : public Strategy
{
public:
std::string DoAlgorithm(const std::vector<std::string> &data) const override
{
std::string result;
std::for_each(std::begin(data), std::end(data), [&result](const std::string &letter) {
result += letter;
});
std::sort(std::begin(result), std::end(result));
return result;
}
};
class ConcreteStrategyB : public Strategy
{
std::string DoAlgorithm(const std::vector<std::string> &data) const override
{
std::string result;
std::for_each(std::begin(data), std::end(data), [&result](const std::string &letter) {
result += letter;
});
std::sort(std::begin(result), std::end(result));
for (int i = 0; i < result.size() / 2; i++)
{
std::swap(result[i], result[result.size() - i - 1]);
}
return result;
}
};
int main()
{
Context *context = new Context(new ConcreteStrategyA);
std::cout << "Client: Strategy is set to normal sorting.\n";
context->DoSomeBusinessLogic();
std::cout << "\n";
std::cout << "Client: Strategy is set to reverse sorting.\n";
context->set_strategy(new ConcreteStrategyB);
context->DoSomeBusinessLogic();
delete context;
return 0;
}
与其他模式关系
- 命令模式 和策略看上去很像, 因为两者都能通过某些行为来参数化对象。 但是它们的意图有非常大的不同。
1.
posted on 2021-05-24 15:28 Ultraman_X 阅读(40) 评论(0) 编辑 收藏 举报