如何在c++中实现静态工厂模式

How to implement a static factory pattern in C++

本文关键字:静态 工厂 模式 实现 c++      更新时间:2023-10-16

我尝试用模板实现静态工厂模式,以a)避免为每个派生类编写相同的代码片段,以及b)回收相同类型的对象。下面的代码可以编译,但不能工作。我不确定这是不是因为我用了智能指针。

这是我的代码:

class ObjMgr
{
public:
    static ObjMgr & Instance();
    template <typename T>
    void Register(const char* name) {
        m_creators[name] = &(ObjCreator<T>);
    }
    Abstract &
        GetObj(const string& objTypeCode);
private:
    ObjMgr(void) {};
    template <typename T>
    static shared_ptr<Abstract>& ObjCreator() {
        return move(std::shared_ptr<Abstract> (new T));
    }
    typedef shared_ptr<Abstract>& (*PObjCreator)();
    std::unordered_map<std::string, PObjCreator> m_creators;
    vector< shared_ptr<Abstract> > m_objs;
    //singleton
    static unique_ptr<ObjMgr> m_instance;
    static std::once_flag m_onceFlag;
    ObjMgr(const ObjMgr &) = default;
    ObjMgr& operator=(const ObjMgr &) = default;
};
Abstract& ObjMgr::GetObj(const string& objTypeCode)
{
    const shared_ptr<Abstract>& obj = m_creators[objTypeCode]();
    m_objs.push_back(move(obj));
    return *(m_objs.back());
}

代码编译,但在运行时,GetObj返回一个空引用。在main()中,派生类型注册为

objMgr.Register<Derived>("Derived");

顺便说一句,我使用了一个向量来保存对象,以便以后可以回收相同类型的对象。

谁能告诉我我做错了什么并告诉我如何改正它?

我发现了问题:对象是在ObjCreator()的堆栈上创建的。我只需要创建静态变量来保存对象:

template <typename T>
static shared_ptr<Abstract>& ObjCreator() {
    static vector<shared_ptr<Abstract>> objs;
    objs.emplace_back(std::make_shared<T>());
    return (objs.back());
}

然后在ObjMgr中,我将做簿记,看看特定类型的对象是否已经存在,以便我可以回收它。

我想可能是你的Register(const char* name)方法和unordered_map<string,…>处于冲突之中。将unordered_map更改为unordered_map代替。

我无法让你的代码编译。

下面的代码可以工作:

请注意,我通常这样做的方式是使用Singleton模板,因为似乎您希望始终获得相同的实例。

如果你想要能够返回不同的实例,那么改变ObjectManager::CreatorFunc中的代码,使'instance'变量不是静态的,而是一个局部变量,或者传递一个不同的CreatorFunc给Register。

stdafx.h:

#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <unordered_map>
#include <memory>
#include <mutex>
#include <iostream>

cpp:

#include "stdafx.h"
class Abstract
{
};
template <typename T>
class Singleton : public Abstract
{
private:
    static T* m_singleton;
public:
    static T& Instance()
    {
        if (m_singleton == 0)
        {
            m_singleton = new T();
        }
        return *m_singleton;
    }
};
template <typename T> T* Singleton<T>::m_singleton;
class ObjectManager : public Singleton<ObjectManager>
{
private:
    typedef Abstract& (*CreatorFuncType)();
    std::unordered_map<const char*, CreatorFuncType> m_creators;
    template <typename T>
    static T& CreatorFunc()
    {
        static T* const instance = new T();
        return *instance;
    }
public:
    template <typename T>
    void Register(const char* name, CreatorFuncType creator = (CreatorFuncType)CreatorFunc<T>)
    {
        m_creators[name] = creator == 0 ? (CreatorFuncType)Singleton<T>::Instance : creator;
    }
    Abstract& ObjectManager::GetObj(const char* name)
    {
        CreatorFuncType creator = m_creators[name];
        return (creator)();
    }
};
class TestClass : Singleton<TestClass>
{
    static int count;
    int myInstance;
public:
    TestClass()
        : myInstance(++count)
    {
        std::cout << "hello in test class ctor instance #" << myInstance << std::endl;
    }
    void TestFunc()
    {
        std::cout << "I'm in the test func with instance #" << myInstance << std::endl;
    }
};
int TestClass::count = 0;
int _tmain(int argc, _TCHAR* argv[])
{
    ObjectManager::Instance().Register<TestClass>("TestClass");
    TestClass &tc = (TestClass&)ObjectManager::Instance().GetObj("TestClass");
    TestClass &tc2 = (TestClass&)ObjectManager::Instance().GetObj("TestClass");
    std::cout << "tc == tc2 is " << (&tc == &tc2 ? "true" : "false") << std::endl;
    std::cout << "tc.... ";
    tc.TestFunc();
    std::cout << "tc2... ";
    tc2.TestFunc();
    char buf[100];
    std::cin >> buf;
    return 0;
}