C++实现工厂设计模式
- 在做Data-Driven设计的时候,我们希望能对象的创建能依运行时文件的读入而不是硬编码在代码里。比如在设计游戏时,我们希望能够做到根据外部配置文件(可由游戏设计器生成)自动生成对象,并且配置好对象的属性。
- 这时,我们需要做到的时根据文件的信息判断处需要创建出哪种类型的对象,这时我们可能想到的方法是
// 从配置文件中解析出typeID
switch (typeID) {
case PLAYER : return Player();
case TANK : return Tank();
case TREE : return Tree();
...
default : return nullptr;
}
- 这样是可行的,但是当我们需要增加新的可能被以这种形式创建的类型的对象时,我们则需要在switch语句中添加新的一行,并且在定义TypeID类型的地方添加新的类型的ID,这显然时不符合开闭原则的。这时,我们可以借助工厂模式实现Data-Driven的创建对象。
- 工厂模式的核心就是工厂类,工厂类提供一个函数,可以根据传入参数代表的欲创建的对象的的类型(TypeID)来创建出对象,总之就是,你喂给它类型,他吐出来这种类型的对象。
定义Object基类:
- 工厂的一个函数可以返回不同类型的对象,所以我们考虑让这些需要被工厂创建的类型都继承于Object类,工厂创建就返回Object的指针类型。并且每个继承于Object的类型都必须手写一个获取类型ID的函数,以实现ID和类型相联系。
class Object {
public:
virtual ~Object() = default;
};
// 定义ID函数辅助宏
#define DEFILE__GET_TYPE_ID(type) \
static const std::string & getTypeID() { \
static const std::string ID = #type; \
return ID; \
}
定义Creator基类:
- 我们需要根据传入的类型ID动态的选择创建哪种类型的对象,Java中的反射可以实现这一点,但是C++没有原生支持的反射,这里我们通过借助Creator实现创建对象,不同的Creator能创建不同类型的对象。
- 届时,我们通过ID检索到Creator然后再通过Creator的创建函数实现对象的创建。为了能将Creator组织起来,我们将定义Creator基类,每个不同类型对应的Creator都将继承于此。
class Creator {
public:
Creator() = default;
virtual Object * create() = 0;
virtual ~Creator() = default;
};
// 定义Creator 辅助宏
#define DEFILE__CREATOR(type) \
class type##Creator : public Creator { \
public: \
type##Creator() = default; \
virtual Object * create() override { \
return new type(); \
} \
virtual ~type##Creator() = default; \
};
定义工厂类的初步结构:
- 我们想要通过ID检索到Creator然后再通过Creator的创建函数实现对象的创建,就要将Creator和ID建立关系并组织起来,这里我们采用std::map。
- 我们的工厂不需要多个,全局只需一个即可,应该设计成单例。
- 并且,我们应该为工厂添加注册方法,实现利用ID和对应的Creator为这种类型的对象注册信息,实现工厂式创建。
class ObjectFactory {
public:
Object * create(const std::string & typeID) {
auto iter = creators.find(typeID);
if (iter != creators.end()) return iter->second->create();
return nullptr;
}
void registe(const std::string & id, Creator * c) {
auto iter = creators.find(id);
if (iter == creators.end()) creators[id] = c;
}
~ObjectFactory() {
for (auto p : creators) {
if (p.second) delete p.second;
}
}
public:
static ObjectFactory * getInstance() {
static ObjectFactory instance;
return &instance;
}
private:
ObjectFactory() = default;
std::map<std::string, Creator*> creators;
};
// 定义注册辅助宏
#define REGISTE(type) \
ObjectFactory::getInstance()->registe( \
type::getTypeID(), new type##Creator());
测试:
class A : public Object {
public:
A() {
std::cout << "A\n";
}
DEFILE__GET_TYPE_ID(A)
};
DEFILE__CREATOR(A)
class B : public Object {
public:
B() {
std::cout << "B\n";
}
DEFILE__GET_TYPE_ID(B)
};
DEFILE__CREATOR(B)
class Player : public Object {
public:
Player() {
std::cout << "Player\n";
}
DEFILE__GET_TYPE_ID(Player)
};
DEFILE__CREATOR(Player)
int main() {
REGISTE(A);
REGISTE(B);
REGISTE(Player);
// in main-function
ObjectFactory::getInstance()->create("A");
ObjectFactory::getInstance()->create("B");
ObjectFactory::getInstance()->create("B");
ObjectFactory::getInstance()->create("Player");
ObjectFactory::getInstance()->create("Player");
return 0;
}
测试结果: