1.策略模式的定义
策略模式常用在算法选用中,其主要是定义一个抽象的算法接口,并通过继承该抽象算法接口对所有算法加以封装和实现,而具体的算法选择过程在客户端中实现。
个人理解上,我觉得策略模式主要适用于需要对某个对象多次转换所用算法时用到。因为这个策略主要是封装一系列算法(当然不止非得是算法,也可以是不同的普通函数),其调用接口已经分配好了,只需要不断地使用调度接口来切换所用的算法即可实现此策略能达到的功能。比如需要不断生产不同型号螺母的流水线,其需要不断地根据当前的螺母型号来变更自己的算法,此时就可以灵活运用策略模式了。
2.策略模式的类图
策略模式的类图如上所示,具体可知Strategy类是一个算法的抽象类,而Content类则直接负责调用这些算法接口,实现相关的功能函数,最后由客户端调用这些功能函数来实现策略模式的过程。具体的介绍如下:
- Strategy抽象类:在其中定义需要重载的虚函数(即相关接口)以及需要公用的基本函数,保证其实例化对象的统一性;
- ConcreteStragety实例类:其继承Stragety抽象类的接口与函数,定义需要具体运用的功能;
- Content类:作为所有Stragety抽象类的组合函数,将Stragety抽象类均作为成员变量,并在内部定义多个功能函数来实现这些成员变量的运用过程,从而将底层的算法流程封装成功能函数,提供使用;
- Client客户端:客户端无需知晓底层的内部算法构造如何,只需要调用Content类封装好的功能函数接口即可。
其中的关键在于,算法的逻辑抽象接口是封装到一个类中的(Content),再通过委托的方式让具体的Strategy类来实现。即先有了Content的需求,再有了Stragety抽象类相关的接口实现等过程。
3.策略模式的代码实现
本例中,Content类为AGV_System类,其定义了三个函数,其中构造函数和SetMethod函数均为定义其内部成员变量的,而DoAciton函数则直接定义了两个Stragety抽象类(AGV_Location和AGV_Move)需要执行的函数CalculatePosition和Movemethod。由此,AGV_Location和AGV_Move作为两个抽象类,其直接在类内分别定义需要重载的虚函数CalculatePosition和Movemethod作为接口。最后的四个实例类则直接继承了两个父类后,简单地实现函数完成实例化过程。
其中稍微一提,由于本人的cpp图方便都是放在一个项目里,在调试此模式和装饰模式的代码有点bug冲突,所以在此处使用了命名空间的方式来定义整个模式对象体。
#include <iostream>
using namespace std;
namespace Strategy
{
class AGV_Location
{
public:
virtual void CalculatePosition() = 0;
};
class Map_Location : public AGV_Location
{
public:
void CalculatePosition()
{
cout << "Using the map to get the position of AGV!" << endl;
}
};
class Lidar_Location : public AGV_Location
{
public:
void CalculatePosition()
{
cout << "Using the lidar to get the position of AGV!" << endl;
}
};
class AGV_Move
{
public:
virtual void MoveMethod() = 0;
};
class TranslationMove : public AGV_Move
{
public:
void MoveMethod()
{
cout << "Using the TranslationMove to move the AGV!" << endl;
}
};
class VehicleMove : public AGV_Move
{
public:
void MoveMethod()
{
cout << "Using the VehicleMove to move the AGV!" << endl;
}
};
class AGV_System
{
public:
AGV_System(AGV_Location *agvloaction, AGV_Move *agvmove)
{
m_agvloaction = agvloaction;
m_agvmove = agvmove;
}
void SetMethod(AGV_Location *agvloaction, AGV_Move *agvmove)
{
m_agvloaction = agvloaction;
m_agvmove = agvmove;
}
void DoAction()
{
m_agvloaction->CalculatePosition();
m_agvmove->MoveMethod();
}
private:
AGV_Location *m_agvloaction;
AGV_Move *m_agvmove;
};
}
using namespace Strategy;
int main()
{
//这里的都是预定义的策略Strategy,严格上不属于Client的调用范围
AGV_Location* maplocation = new Map_Location;
AGV_Location* lidarlocation = new Lidar_Location;
AGV_Move* translationmove = new TranslationMove;
AGV_Move* vehiclemove = new VehicleMove;
//先在构造函数中定义策略,然后重新定义新的策略
AGV_System *agvsystem = new AGV_System(maplocation, translationmove);
agvsystem->DoAction();
agvsystem->SetMethod(lidarlocation, vehiclemove);
agvsystem->DoAction();
delete maplocation;
delete lidarlocation;
delete translationmove;
delete vehiclemove;
delete agvsystem;
return 0;
}