Chapter11:抽象工厂模式
先说下之前用到过的【工厂方法模式】是定义一个用于创建对象的接口。让子类决定实例化哪一个类。
再说【抽象工厂模式(Abstract Factory)】,提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。
实际应用
代码工程结构:
(1)产品A ProductA.h
(2)产品B ProductB.h
(3)工厂类 Factory.h
(4)客户端 AbstractFactoryApp.cpp
(1)产品A ProductA.h
#ifndef _PRODUCT_A_
#define _PRODUCT_A_
#include <iostream>
using namespace std;
class AbstractProductA
{
public:
virtual void GetA(void) = 0;
};
class ProductA1 : public AbstractProductA
{
void GetA(void)
{
cout << "Product1的GetA方法\n";
}
};
class ProductA2 : public AbstractProductA
{
void GetA(void)
{
cout << "Product2的GetA方法\n";
}
};
#endif //_PRODUCT_A_
(2)产品B ProductB.h
#ifndef _PRODUCT_B_
#define _PRODUCT_B_
#include <iostream>
using namespace std;
class AbstractProductB
{
public:
virtual void GetB(void) = 0;
};
class ProductB1 : public AbstractProductB
{
void GetB(void)
{
cout << "Product1的GetB方法\n";
}
};
class ProductB2 : public AbstractProductB
{
void GetB(void)
{
cout << "Product2的GetB方法\n";
}
};
#endif //_PRODUCT_B_
(3)工厂类 Factory.h
#ifndef _FACTORY_H_
#define _FACTORY_H_
#include "ProductA.h"
#include "ProductB.h"
class AbstractFactory
{
public:
virtual AbstractProductA* CreateProductA() = 0;
virtual AbstractProductB* CreateProductB() = 0;
};
class ConcreteFactory1 : public AbstractFactory
{
public:
ProductA1* CreateProductA()
{
m_pProductA1 = new ProductA1();
return m_pProductA1;
}
ProductB1* CreateProductB()
{
m_pProductB1 = new ProductB1();
return m_pProductB1;
}
private:
ProductA1* m_pProductA1;
ProductB1* m_pProductB1;
};
class ConcreteFactory2 : public AbstractFactory
{
public:
ProductA2* CreateProductA()
{
m_pProductA2 = new ProductA2();
return m_pProductA2;
}
ProductB2* CreateProductB()
{
m_pProductB2 = new ProductB2();
return m_pProductB2;
}
private:
ProductA2* m_pProductA2;
ProductB2* m_pProductB2;
};
#endif //_FACTORY_H_
(4)客户端 AbstractFactoryApp.cpp
// AbstractFactoryApp.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "Factory.h"
void FreeMemory(void* Pointer)
{
if (NULL != Pointer)
{
free(Pointer);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
// 只需要确定实例化哪一个Product对象给factory,这里我们用ConcreteFactory1来初始化
// AbstractFactory* pFactory = new ConcreteFactory2();
AbstractFactory* pFactory = new ConcreteFactory1();
// 此时与具体的Product访问解除了依赖
AbstractProductA* pProductA = pFactory->CreateProductA();
pProductA->GetA();
AbstractProductB* pProductB = pFactory->CreateProductB();
pProductB->GetB();
system("pause");
FreeMemory(pFactory);
return 0;
}
抽象工厂模式的优点和缺点:
最大的好处便是易于交换产品系列,由于具体工厂类,例如 AbstractFactory* pFactory = new ConcreteFactory1(), 在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。我们的设计不能去防止需求的改变,那么我们的理想便是让改动变得最小。
第二大好处是,它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。
缺点是:如果你的需求来自增加功能,比如我们现在要增加新的 AbstractProductC,我们需要改动哪些地方?至少要增加三个类AbstractProductC、ProductC1、ProductC2才可以完全实现。
用简单工厂来改进抽象工厂
去除AbstractFactory、ConcreteFactory1、ConcreteFactory2三个工厂类,取而代之的是ProductAccess类,用一个简单工厂模式来实现。
实际应用
工程结构
(1)产品A ProductA.h
(2)产品B ProductB.h
(3)产品创建控制 ProductAccess.h
(4)客户端 ReflectionApp.cpp
(1)产品A ProductA.h
#ifndef _PRODUCT_A_
#define _PRODUCT_A_
#include <iostream>
using namespace std;
class AbstractProductA
{
public:
virtual void GetA(void) = 0;
};
class ProductA1 : public AbstractProductA
{
void GetA(void)
{
cout << "Product1的GetA方法\n";
}
};
class ProductA2 : public AbstractProductA
{
void GetA(void)
{
cout << "Product2的GetA方法\n";
}
};
#endif //_PRODUCT_A_
(2)产品B ProductB.h
#ifndef _PRODUCT_B_
#define _PRODUCT_B_
#include <iostream>
using namespace std;
class AbstractProductB
{
public:
virtual void GetB(void) = 0;
};
class ProductB1 : public AbstractProductB
{
void GetB(void)
{
cout << "Product1的GetB方法\n";
}
};
class ProductB2 : public AbstractProductB
{
void GetB(void)
{
cout << "Product2的GetB方法\n";
}
};
#endif //_PRODUCT_B_
(3)产品创建控制 ProductAccess.h
#ifndef _PRODUCT_ACCESS_H_
#define _PRODUCT_ACCESS_H_
#include <string>
#include <map>
using namespace std;
/************************************************************************
* description: 实现了注册类实例指针及其类名字符串的类模版
* remark:
************************************************************************/
template<class TBase, typename ClassID = string> class CFactory
{
private:
CFactory(){}
CFactory(const CFactory&){}
CFactory& operator=(const CFactory&){}
typedef TBase*(*BasePtr)();
map<ClassID, BasePtr> m_mapRegInfo;
public:
static CFactory& Instance()
{
static CFactory<TBase, ClassID> bf;
return bf;
}
// 实现注册<类名, 类实例指针>
void RegBasePtr(const ClassID& classname, BasePtr fn)
{
m_mapRegInfo[classname] = fn;
}
// 实现通过类名获取其实例指针。如果未注册则返回空指针
TBase* GetRegPtr(const ClassID& classname) const
{
TBase* BaseObj = NULL;
map<ClassID, BasePtr>::const_iterator regEntry = m_mapRegInfo.find(classname);
if (regEntry != m_mapRegInfo.end())
{
BaseObj = regEntry->second();
}
return BaseObj;
}
};
// 调用CFactory<BASE_CLASS>类类型的静态成员函数通过类名获取对应的实例指针,如果该类名没有注册过,返回空指针
#define CREATE_CLASS(BASE_CLASS, DERIVED_CLASS) CFactory<BASE_CLASS>::Instance().GetRegPtr(DERIVED_CLASS)
/************************************************************************
* description: 执行注册类实例指针以及对应的类名信息的类模版
* remark:
************************************************************************/
template<class TBase, class TDerived, typename ClassID = string> class RegToFactory
{
public:
static TBase* CreateInstance()
{
return (new TDerived());
}
RegToFactory(const ClassID& id)
{
CFactory<TBase, ClassID>::Instance().RegBasePtr(id, CreateInstance);
}
};
// 定义一个RegToFactory<BASE_CLASS, DERIVED_CLASS>类类型的对象Register##DERIVED_CLASS,在执行构造函数时带入类名对应的字符串
#define REGISTER_CLASS(BASE_CLASS, DERIVED_CLASS) RegToFactory<BASE_CLASS, DERIVED_CLASS> Register##DERIVED_CLASS(#DERIVED_CLASS)
#endif// _PRODUCT_ACCESS_H_
(4)客户端 ReflectionApp.cpp
// ReflectionApp.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "ProductAccess.h"
#include "ProductA.h"
#include "ProductB.h"
REGISTER_CLASS(AbstractProductA, ProductA1);
REGISTER_CLASS(AbstractProductA, ProductA2);
REGISTER_CLASS(AbstractProductB, ProductB1);
REGISTER_CLASS(AbstractProductB, ProductB2);
int _tmain(int argc, _TCHAR* argv[])
{
AbstractProductA* pBaseA = NULL;
AbstractProductB* pBaseB = NULL;
pBaseA = CREATE_CLASS(AbstractProductA, "ProductA1");
if (NULL != pBaseA)
{
pBaseA->GetA();
delete pBaseA;
pBaseA = NULL;
}
pBaseB = CREATE_CLASS(AbstractProductB, "ProductB1");
if (NULL != pBaseB)
{
pBaseB->GetB();
delete pBaseB;
pBaseB = NULL;
}
system("pause");
return 0;
}
看到这里不知道你发现了没?这个工程里用到了一个在C#或JAVA里很出名的特性:反射
摘自MSDN上对反射的定义:反射提供了封装程序集、模块和类型的对象(Type类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。
在这里我参考了网上牛人们的代码,用C++简单的实现了反射。或许说这种反射是个“形似神不似的反射”。
因为在C#和JAVA中的反射远比“这里的反射”功能强大的多。