文章目录
前言
上一篇讲到简单工厂模式。
在我的理解中工厂的存在就是,为了实例化对象。根据不同条件实例化不同的对象的作用。
这篇博客写的策略模式,可以说是把这个根据不同情况实例化不同对象的这个过程再一次封装了。简而言之就是,策略模式对变化进行了封装。
有点迷。且听我娓娓道来。
1.简单工厂模式回顾
上一节我们画了一个这样的类图。
客户如果想操作导出,其实需要知道两个类的对象。
一个是操作的接口类 E x p o r t O p e r a t i o n ExportOperation ExportOperation,另一个是 E x p o r t F a c t o r y ExportFactory ExportFactory。
前者是为了执行导出操作,后者是为这个类的对象指针实例化特定类型的对象。
2.策略模式
导出可以分为文本导出和图片导出,这种分类的情况其实就是算一种策略。
我们这里区分文本和图片导出,是通过导出工厂ExportFactory的函数去创建对象。这个调用函数创建对象的操作是显式的调用的;同时创建完对象之后,再由导出操作去调用导出操作。这么做简单举例是可以,如果更加合理一些的话,应该是有一个对象去调用这个导出操作吧?而不是导出操作自己去调用导出。
所以这里应该还需要一个类,它有导出的一些操作。同时创建导出对象的过程是显式调用,也就是用户要知道我有这个工厂类,要知道有这么个函数,才可以使用。这样是不是就麻烦了呢?
前言部分我说,策略模式是对变化进行了封装。也就是说,策略模式的效果能够做到这个创建对象的过程隐藏掉了,对于用户来说不管什么工厂之类的了。那么再结合一下刚才说的,应该有一个类去调用导出操作,我们画一个新的类图。
3.策略模式+简单工厂的结合
在这个类图中,Context表示文本,我们可以在Context初始化的时候传递一个字符串,再根据字符串实例化对应的导出操作对象。
这样是不是就相当于把工厂类隐藏了,同时让Context类的成员变量m_pExOp去调用exportData即可。
#include<iostream>
using namespace std;
class ExportOperation
{
public:
virtual void exportData() {};
};
class ExportText :public ExportOperation
{
public:
void exportData() override;
};
class ExportImage :public ExportOperation
{
public:
void exportData() override;
};
enum OperationType
{
text = 1,
image
};
class Context
{
public:
Context() {};
Context(OperationType type)
{
switch (type)
{
case text:
{
m_pExOP = new ExportText();
break;
}
case image:
{
m_pExOP = new ExportImage();
break;
}
default:
break;
}
}
void ExportData()
{
m_pExOP->exportData();
}
private:
ExportOperation* m_pExOP{ nullptr };
};
int main()
{
Context* m_pContext=new Context(OperationType::image);
m_pContext->ExportData();
return 0;
}
总结
在看策略模式的时候,我其实挺奇怪它和简单工厂有什么区别。因为看书中的代码感觉变化不是很大。
后来仔细对比了一下发现:
策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
我的例子中,都是导出这个工作,导出文本算一种算法,导出图片又是另一种算法。但是他们其实都是通过导出这个操作去调用,这就减少了减少了各种算法类(导出文本)与使用算法类(导出操作)之间的耦合。同时,针对导出文本这种算法,我们可以单独测试,并不会影响其他的算法。