工厂模式

工厂方法

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
}

多态工厂


参考资料
1、https://zhuanlan.zhihu.com/p/161422182

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容