这里的动态配置工厂,是指添加一个产品类时,不必去修改工厂类的代码,即可使工厂具备创建产品的能力。
为了描述简便,代码采用教科书中方式而非实际的代码。
我们有以下一组类:
//vehicle.h
class
Vehicle
{
public
:
Vehicle(){}
virtual ~Vehicle(){}
virtual void Start() = 0;
};
//car.h
class
Car : public Vehicle
{
public
:
Car(){}
virtual ~Car(){}
virtual void Start();
};
//car.cpp
void
Car::Start()
{
cout << "Car::Start" << endl;
}
//plane.h
class
Plane : public Vehicle
{
public
:
Plane(){}
virtual ~Plane(){}
virtual void Start();
};
//plane.cpp
void
Plane::Start()
{
cout << "Plane::Start" << endl;
}
通常,我们会使用最简单的工厂方式来创建具体对象,如果对象需要序列化到文件,我们一般会采用字符串作为标记来创建对象。
//verhiclefactory.h
class
VehicleFactory
{
public
:
VehicleFactory();
~VehicleFactory();
Vehicle* Create(const char *name)
{
Assert(name);
if (0 == stricmp(name,"car")) {
return new Car();
}
else if (0 == stricmp(name,"plane")) {
return new Plane();
}
return NULL;
}
};
//main.cpp
int
_tmain(int argc, _TCHAR* argv[])
{
VehicleFactory factory;
Vehicle * car = factory.Create("car");
if (car) {
car->Start();
}
system("pause");
return 0;
}
以上方式在大多数的情况下工作良好。当我们要添加一个具体交通工具类时,记得去修改VehicleFactory,添加一行代码即可。
但若我们要添加的产品类不在VehicleFactory所在的库或者说我们根本无法修改VehicleFactory的代码时。这中方式就很难奏效了。
下面是一种改进的方法,即在添加具体类时把创建逻辑注册给VehicleFactory。
//vehicle.h
class
Vehicle
{
public
:
Vehicle(){}
virtual ~Vehicle(){}
virtual void Start() = 0;
virtual const char* GetClassTag() const = 0;
};
typedef
Vehicle* (*Create_Vehicle)();
#define
DECLARE_FACTORY() /
virtual const char* GetClassTag() const;/
static Vehicle* CreateObject();
#define
IMPLEMENT_FACTORY(class_name,class_tag) /
const char* class_name::GetClassTag() const /
{/
return class_tag;/
}/
Vehicle* class_name::CreateObject() /
{/
return new class_name();/
}/
CreateEntryRegistry::AddCreateEntry add##class_name##create_entry(class_tag,class_name::CreateObject);
上面两个宏定义一个CreateObject的静态函数,用来创建具体的产品对象,程序在运行的时候把这个函数注册给CreateEntryRegistry。
注意最后一行:它定义一个CreateEntryRegistry::AddCreateEntry 的全局对象,它的唯一作用是,在main函数运行之前,调用CreateEntryRegistry::AddCreateEntry的构造函数,自动把CreateObject注册到CreateEntryRegistry中。
class
CreateEntryRegistry
{
public
:
static CreateEntryRegistry* Instance();
bool Register(const char *name,Create_Vehicle create_entry);
Vehicle* Create(const char *name);
struct AddCreateEntry
{
AddCreateEntry(const char *name,Create_Vehicle create_entry)
{
CreateEntryRegistry::Instance()->Register(name,create_entry);
}
};
struct CompStringNoCase : public std::binary_function<string,string,bool>
{
bool operator()(const string &left,const string &right) const
{
return ::stricmp(left.c_str(),right.c_str()) < 0;
}
};
private
:
CreateEntryRegistry(){}
~CreateEntryRegistry(){}
CreateEntryRegistry(const CreateEntryRegistry&);
CreateEntryRegistry& operator = (const CreateEntryRegistry&);
private
:
typedef map<string,Create_Vehicle,CompStringNoCase> CreateEntryMap;
CreateEntryMap m_createEntries;
};
CreateEntryRegistry* CreateEntryRegistry::Instance()
{
static CreateEntryRegistry instance;
return &instance;
}
bool
CreateEntryRegistry::Register(const char *name,Create_Vehicle create_entry)
{
assert(name);
assert(create_entry);
std::pair<CreateEntryMap::iterator,bool> ret =
m_createEntries.insert(std::make_pair(string(name),create_entry));
return ret.second;
}
Vehicle* CreateEntryRegistry::Create(const char *name)
{
if (NULL == name) return NULL;
CreateEntryMap::iterator p = m_createEntries.find(string(name));
if (p != m_createEntries.end() && p->second)
{
return (*p->second)();
}
return NULL;
}
CreateEntryRegistry
是一个Singleton,它管理注册进来的创建函数。用来协助创建对象。有了它,VehicleFactory 变为:
//vehiclefactory.h
class
VehicleFactory
{
public
:
VehicleFactory();
~VehicleFactory();
Vehicle* Create(const char *name)
{
return CreateEntryRegistry::Instance()->Create(name);
}
};
具体类只需在自己的定义文件和实现文件分别添加
DECLARE_FACTORY
和IMPLEMENT_FACTORY 两个宏就可以使VehicleFactory具有创建它们的能力。
//car.h
class
Car : public Vehicle
{
public
:
Car(){}
virtual ~Car(){}
virtual void Start();
DECLARE_FACTORY()
};
//car.cpp
IMPLEMENT_FACTORY(Car,"Car")
void
Car::Start()
{
cout << "Car::Start" << endl;
}
//plane.h
class
Plane : public Vehicle
{
public
:
Plane(){}
virtual ~Plane(){}
virtual void Start();
DECLARE_FACTORY()
};
//plane.cpp
IMPLEMENT_FACTORY(Plane,"plane")
void
Plane::Start()
{
cout << "Plane::Start" << endl;
}
在一些知名的框架中就是采用类似的思路实现对象创建功能的。在实际的软件代码中采用这种方式,能大大提高软件的灵活性,复用性。
2007/11/24