设计模式均整理自李建忠老师的设计模式入门课
策略模式
策略模式属于组件协作模式地一种。
1、定义
将一系列算法一一封装,并它们可以互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展、子类化)。
进一步讨论:此处的算法属于在使用中不断变化的,通过封装不同的算法,继承自同一个父类,则可以在运行时,根据需要来调用不同的算法,而不是在编译时将所有的算法同时编译。
2、动机
- 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。
- 如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?
3、实例与分析
#include <algorithm>
#include <iostream>
#define free_ptr(p) if(p) delete p; p = nullptr;
//strategy 类,定义所有支持的算法的公共接口
class Strategy
{
public:
virtual ~Strategy() {};
virtual void AlgorithmInterface() = 0;
};
//ConcretStrategy 封装具体的算法,继承子Strategy
class ConcreteStrategyA : public Strategy
{
void AlgorithmInterface()
{
std::cout << "算法A实现" << std::endl;
}
};
class ConcreteStrategyB : public Strategy
{
public:
void AlgorithmInterface()
{
std::cout << "算法B实现" << std::endl;
}
};
class ConcreteStrategyC : public Strategy
{
public:
void AlgorithmInterface()
{
std::cout << "算法C实现" << std::endl;
}
};
//context 用一个ConcreteStrategy来配置,维护一个对Strategy的引用
class Context
{
public:
Context(Strategy* strategy) : m_strategy(strategy) { };
~Context() { free_ptr(m_strategy); }
void AlgorithmInterface()
{
m_strategy->AlgorithmInterface();
}
private:
Strategy *m_strategy;
};
int main()
{
Strategy* A = new ConcreteStrategyA();
Strategy* B = new ConcreteStrategyB();
Strategy* C = new ConcreteStrategyC();
A->AlgorithmInterface();
B->AlgorithmInterface();
C->AlgorithmInterface();
free_ptr(A);
free_ptr(B);
free_ptr(C);
return 0;
}
运行结果:
算法A实现
算法B实现
算法C实现
在这段代码中,由于A、B、C三种算法具有相同的基础结构,为了减少代码的重复性,设置一个基类,包含他们的共性,A、B、C三种算法去继承其共性部分并实现该功能。则在main函数运行时,声明基类的算法,然后仅需要针对不同的需要,调用对应的子类,即可实现对应的给功能。
4、使用场景
1、许多相关的类仅仅是行为有异。Strategy模式提供了一种用多个行为中的一个行为来配置一个类的方法。
2、需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间 /时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式。
3、 算法使用客户不应该知道的数据。可使用Strategy模式以避免暴露复杂的、与算法相关的数据结构。
4、一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的 Strategy类中以代替这些条件语句。
5、优缺点
优点:策略模式把算法进行归纳,使得算法的切换、扩展更加容易。
缺点:策略使用者需要了解各个具体策略,使得整个模式的封装性不强。
6、总结要点
- Strategy模式及其子类未组件提供了一系列可复用的算法,从而使得类型在运行时,可以方便地根据需要在各个算法之前进行切换。
- Strategy模式提供了一种不使用条件判断语句地选择。消除条件判断语句就是在解耦合,含有多种条件判断语句布局维护成本较高,逻辑较为混乱。使用Strategy模式可以有效避免该问题。
- 如果Strategy对象没有实例对象,那么上下文可以共享同一个Strategy对象,从而节省对象开销。
整理自:
http://mtw.so/5YfjSP
https://github.com/Bigmartin121/C-plusplus-design-patterns-Li/tree/main/Strategy