一、简单工厂模式

实例Demo1
?1、基本概念
工厂模式又称工厂设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。
主要目的是定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。提高了代码的扩展性,屏蔽每一个功能类中的具体实现逻辑。让外部可以更加简单地只知道调用即可。
2、结构图
定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。

Factory(工厂):核心部分,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象。
Product(抽象类产品):工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象。
ConcreteProduct(具体产品):简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。它要实现抽象产品中声明的抽象方法。
3、实现案例
案例背景:音频编码格式分AAC、AACLD、ADPCM、G711等等,而播放某次音频只需要创建某个编码类型的类(初始化某个类的资源等)即可。
1、工厂类
class CAEncManager
{
public:
CAEncManager();
~CAEncManager();
HRESULT CreateEncHandle(AudioEncodeTypeEx enDataType);
HRESULT RegisterEncodeDataCallBack(AudioParam *pstAudioParam, OutputDataCallBackEx pfnOutputDataCallBack, void* pUser);
HRESULT StartEncode();
HRESULT InputEncodeData(unsigned char* pData, int dwDataLen);
HRESULT StopEncode();
HRESULT DestroyHandle();
private:
void ReleaseEncode();
private:
...
HK_Mutex m_csEncMutex; ///< 保护锁
};
HRESULT CAEncManager::CreateEncHandle(AudioEncodeTypeEx enDataType)
{
try{
switch (m_nEncType)
{
case AUDIO_TYPE_PCM:
m_pcCodec = HK_NULL;
break;
case AUDIO_TYPE_G711A:
if (HK_NULL == m_pcCodec)
{
m_pcCodec = new CCodecG711(G711A);
}
break;
case AUDIO_TYPE_G711U:
if (HK_NULL == m_pcCodec)
{
m_pcCodec = new CCodecG711(G711U);
}
break;
case AUDIO_TYPE_G722:
if (HK_NULL == m_pcCodec)
{
m_pcCodec = new CCodecG722();
}
break;
...
default:
return AUDIOCOM_E_PARA;
}
}
catch(...)
{
printf("CreateEncHandle failed enDataType:%d\n",enDataType);
return AUDIOCOM_E_RESOURCE;
}
return AUDIOCOM_OK;
}
AEncManager.h作为工厂类。其中的CreateHandle根据外部传入的编码格式进行内部编码类的构建。
2、抽象类产品
class ICodec
{
public:
///<析构函数
virtual ~ICodec() {};
///<初始化编码参数
virtual HRESULT InitEncode(参数1,参数2,参数3) = HK_NULL;
///<输入编码数据
virtual HRESULT InputEncodeData(HK_BYTE* pData, INT32_U dwDataLen) = HK_NULL;
///<设置回调函数
virtual HRESULT SetCallBack(OutputDataCallBackEx pfnOutputDataCallBack, void* pUser) = HK_NULL;
///<初始化解码参数
virtual HRESULT InitDecode(pcm采样率,声道个数,<编码比特率) = HK_NULL;
///<输入解码数据
virtual HRESULT InputDecodeData(HK_BYTE* pData, INT32_U dwDataLen) = HK_NULL;
};
各类编码格式实现的父类。
3、具体产品
以AAC为例,AAC实现类是抽象类的子类。
class CCodecAAC : public ICodec
{
public:
///<构造函数
CCodecAAC();
///<析构函数
virtual ~CCodecAAC();
///<初始化编码参数
int InitEncode(int nSampleRate, int nChannel, int nBitRate);
///<输入编码数据
int InputEncodeData(HK_BYTE* pData, int dwDataLen);
///<设置回调函数
int SetCallBack(OutputDataCallBackEx pfnOutputDataCallBack, void* pUser);
///<初始化解码参数
int InitDecode(int nSampleRate, int nChannel, int nBitRate);
///<输入解码数据
int InputDecodeData(HK_BYTE* pData, int dwDataLen,HK_BYTE* pDecodeBuffer, int& decLen);
private:
void InitMemset();
private:
/*****************编码参数*****************************************************/
参数1;
参数2;
......
/******************解码参数****************************************************/
参数1;
参数2;
......
};
AAC编码类里面会将PCM数据编码为AAC数据。
二、工厂方法
目的:简单工厂的延伸,弥补简单工厂的缺陷。
方法:父类工厂负责定义创建产品对象的公共接口,子类工厂负责生产具体的产品对象。产品类的实例化操作延迟到工厂子类中完成。

实例Demo2

三、抽象工厂
目的:泛华工厂方法模式,让每个具体工厂可以生产多个具体商品。
方法:在一个工厂里聚合多个同类产品,即打包生产。

案例Demo3

?
上层
CAEncDecManager* pHandle=NULL;
switch(encDecType)
{
case 1:
pHandle = new CAEncManager();
break;
case 2:
pHandle = new CADecManager();
break;
}
pHandle->CreateAACEncDecHandle();//创建AAC解码
四、总结
模式名称 | 优缺点 | 案例分析 | 适用场景 | 简单工厂 | 优:实现对象创建和对象适用的分割 缺:灵活度不足,违反“开闭原则” | Demo1中的CCodecAAC中 既有编码功能又有解码功能 | 简单的生产结构 | 工厂方法模式 | 优:比简单工厂灵活性和可扩展性更好 缺:类的个数成本增加,产品单一化 | Demo2中抽象工厂下面有很多具体工厂,类个数较多 | 单一产品的扩展 | 抽象工厂模式 | 优:扩展了工厂方法,增加或替换产品族比较方便 缺:类的数量庞大,复杂度高,增/换产品结构比较困难 | Demo3中类更多 | 产品套件的扩展 |
|