策略模式
定义一系列的算法,把他们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。属于行为型模式。
适用场景
1、许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
2、需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间 /时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式。
3、 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
4、一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的 Strategy类中以代替这些条件语句。
优缺点
优点:策略模式把算法进行归纳,使得算法的切换、扩展更加容易。
缺点:策略使用者需要了解各个具体策略,使得整个模式的封装性不强。
UML图
环境类(Context): 内部维护一个Strategy对象的引用,对外提供相应功能接口;
策略类(Strategy): 定义算法的一个或多个接口;
具体策略类(ConcreteStrategy): 实现Strategy定义的接口,提供具体算法的实现;
代码实现
Strategy.h
#pragma once
// 抽象策略
class Strategy
{
public:
Strategy() {};
virtual ~Strategy() {};
virtual void AlgorithmInterface(double num1, double num2) = 0;
};
// 加法
class StrategyAdd : public Strategy
{
public:
void AlgorithmInterface(double num1, double num2);
};
// 减法
class StrategySubstract : public Strategy
{
public:
void AlgorithmInterface(double num1, double num2);
};
// 乘法
class StrategyMultiply : public Strategy
{
public:
void AlgorithmInterface(double num1, double num2);
};
// 除法
class StrategyDivide : public Strategy
{
public:
void AlgorithmInterface(double num1, double num2);
};
Strategy.cpp
#include "Strategy.h"
#include <iostream>
void StrategyAdd::AlgorithmInterface(double num1, double num2)
{
std::cout << num1 << " + " << num2 << " = " << num1 + num2 << std::endl;
}
void StrategySubstract::AlgorithmInterface(double num1, double num2)
{
std::cout << num1 << " - " << num2 << " = " << num1 - num2 << std::endl;
}
void StrategyMultiply::AlgorithmInterface(double num1, double num2)
{
std::cout << num1 << " × " << num2 << " = " << num1 * num2 << std::endl;
}
void StrategyDivide::AlgorithmInterface(double num1, double num2)
{
std::cout << num1 << " ÷ " << num2 << " = " << num1 / num2 << std::endl;
}
Context.h
#pragma once
class Strategy;
class Context
{
public:
Context(Strategy *pStrategyArg) : m_pStrategy(pStrategyArg) {}
void ContextInterface(double num1, double num2);
private:
Strategy *m_pStrategy = nullptr;
};
Context.cpp
#include "Context.h"
#include "Strategy.h"
void Context::ContextInterface(double num1, double num2)
{
m_pStrategy->AlgorithmInterface(num1, num2);
}
main.cpp
#include "Strategy.h"
#include "Context.h"
#include <process.h>
int main()
{
auto pStrategyAdd = new StrategyAdd;
auto pStrategySubstract = new StrategySubstract;
auto pStrategyMultiply = new StrategyMultiply;
auto pStrategyDivide = new StrategyDivide;
auto pContextA = new Context(pStrategyAdd);
auto pContextB = new Context(pStrategySubstract);
auto pContextC = new Context(pStrategyMultiply);
auto pContextD = new Context(pStrategyDivide);
pContextA->ContextInterface(1.23, 4.56);
pContextB->ContextInterface(1.23, 4.56);
pContextC->ContextInterface(1.23, 4.56);
pContextD->ContextInterface(1.23, 4.56);
if (pStrategyAdd) delete pStrategyAdd;
if (pStrategySubstract) delete pStrategySubstract;
if (pStrategyMultiply) delete pStrategyMultiply;
if (pStrategyDivide) delete pStrategyDivide;
if (pContextA) delete pContextA;
if (pContextB) delete pContextB;
if (pContextC) delete pContextC;
if (pContextD) delete pContextD;
system("pause");
return 0;
}
输出
总结
策略模式和状态模式,是大同小异的;状态模式讲究的是状态的变化,和不同状态下,执行的不同行为;而策略模式侧重于同一个动作,实现该行为的算法的不同,不同的策略封装了不同的算法。策略模式适用于实现某一功能,而实现该功能的算法是经常改变的情况。在实际工作中,遇到了实际的场景,可能会有更深的体会。比如,我们做某一个系统,该系统可以适用于各种数据库,我们都知道,连接某一种数据库的方式是不一样的,也可以说,连接数据库的“算法”都是不一样的。这样,我们就可以使用策略模式来实现不同的连接数据库的策略,从而实现数据库的动态变换。