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中的反射远比“这里的反射”功能强大的多。

 

posted @ 2010-08-26 22:55  奋斗の机器  阅读(208)  评论(0编辑  收藏  举报