工厂方法
class db_interface { ... };
class mysql_db : public db_interface { ... };
class mem_db : public db_interface { ... };
class sqllite_db : public db_interface { ... };
class db_creator
{
public:
static db_interface* creat_db(const char* pConnStr);
...
};
db_interface* db_creator::create_db(const char* pConnStr);
{
db_interface* p_Conn = nullptr;
if (strstr(pConnStr, "mysql_type") == pConnStr)
{
pConn = new mysql_db(pConnStr);
}
else if (...)
{
...
}
return p_Conn;
}
这里,最简单的情况,工厂返回的是基类裸指针,如果需要返回std::unique_ptr<Base>
(独占所有权)或者std::shared_ptr<Base>
(共享所有权)。
动态类型注册
到目前为止,在编译期对象的类型都是已知的,所以我们可以通过标识符来产生确定的对象,相当于在工厂方法中我们对所有类型的对象进行了硬编码,如果某种派生类没有添加到工厂中,则工厂无法产生该派生类。如果我们添加一种新的派生类,工厂方法需要再增加switch一个分支,这样随着派生类的增多,工厂方法变得不可维护。
class building;
typedef building* (*building_factory)(); // typedef将BuildingFactory工厂方法返回为建筑指针
int building_type_count = 0;
std::vector<std::pair<int, building_factory>> building_registry; // key为标识符,value是建筑指针。通过vector保存此map
void register_building(building_factory factory)
{
// 注册表,用来注册建筑,调用RegisterBuilding注册使,key每次+1
building_registry.push_back(std::make_pair(building_type_count++, factory));
}
class building
{
public:
// 通过make_building方法使派生类有构造自己的能力
static auto make_building(int building_type)
{
building_factory factory = building_registry[building_type].second; // 取building_registry的value值
return std::unique_ptr<building>(factory());
}
};
class mysql_db_build : public building
{
public:
// 调用register_building注册自己
static void register() { ::register_building(mysql_db_build::make_building); }
// 通过make_building方法使派生类有构造自己的能力
static building* make_building() { return new mysql_db(); }
};
class mem_db_build : public building
{
public:
// 调用register_building注册自己
static void building() { ::register_building(mem_db_build::make_building); }
// 通过make_building方法使派生类有构造自己的能力
static building* make_building() { return new mem_db_build(); }
};
int main()
{
mysql_db_build::register(); // 注册mysql_db_build ,第一个注册,key为0
mem_db_build::register(); // 注册mem_db_build,第二个注册,key为1
std::unique_ptr<Building> b0 = building::make_building(0); // 通过基类building,取key为0
std::unique_ptr<Building> b1 = building::make_building(1); // 通过基类building,取key为1
}