首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >游戏引擎ObjectFactory类

游戏引擎ObjectFactory类
EN

Code Review用户
提问于 2015-04-09 04:40:14
回答 1查看 547关注 0票数 2

作为游戏引擎的一部分,我为一个工厂开发了一个模板类,它管理一种特定类型的对象。工厂通过字符串标识符处理初始化、销毁和访问先前创建的对象。

它允许向带有各种参数的对象构造函数转发参数,并与命名空间中的一些独立函数进行接口。因为每个对象类型都有自己的工厂,所以工厂是由Game类自动创建和管理的(在实际代码中,Game是一个单例,并处理一堆东西,但是在下面的简化代码中,Game只是删除所有自动创建的工厂)。

可以将以下代码复制到文件中并进行编译,它将按预期运行,并包含一个简单的示例。启用C++11编译。

代码语言:javascript
复制
#include <iostream>
#include <map>
#include <vector>
#include <functional>
#include <memory>

namespace TGE
{
    class FactoryBase
    {
        public:
            virtual void destroy() = 0;
    };

    class Game
    {
        public:
            void manageFactory(FactoryBase* factory)
            {
                _factoryStack.push_back(factory);
            }

            void destroy()
            {
                while(!_factoryStack.empty())
                {
                    _factoryStack.back()->destroy();
                    _factoryStack.pop_back();
                }
            }

        private:
            std::vector<FactoryBase*> _factoryStack;
    } MyGame;

    // Forward declare template function for friendship later in ObjectFactory
    template<class ObjectClass>
    std::vector<std::string> objectList();

    template<class ObjectClass>
    class ObjectFactory : public FactoryBase
    {
        public:
            void destroy()
            {
                if(_instance != nullptr)
                    delete _instance;
            }

            static ObjectFactory<ObjectClass>* instance()
            {
                if(_instance == nullptr)
                    _instance = new ObjectFactory<ObjectClass>();

                return _instance;
            }

            template<typename... Args>
            std::shared_ptr<ObjectClass> createObject(std::string id, Args&&... args)
            {
                objectMap[id] = std::shared_ptr<ObjectClass>
                                               (new ObjectClass(std::forward<Args>(args)...));
                return objectMap[id];
            }

            std::shared_ptr<ObjectClass> getObject(std::string id)
            {
                if(objectMap.find(id) != objectMap.end())
                    return objectMap[id];

                return nullptr;
            }

            void deleteObject(std::string id)
            {
                if(objectMap.find(id) != objectMap.end())
                    objectMap.erase(id);
            }

        private:
            ObjectFactory<ObjectClass>() { MyGame.manageFactory(this); }
            ~ObjectFactory<ObjectClass>() {}

            static ObjectFactory<ObjectClass>* _instance;

            friend std::vector<std::string> objectList<ObjectClass>();

            std::map<std::string, std::shared_ptr<ObjectClass>> objectMap;
    };

    template<class ObjectClass>
    ObjectFactory<ObjectClass>* ObjectFactory<ObjectClass>::_instance = nullptr;

    template<class ObjectClass, typename... Args>
    std::shared_ptr<ObjectClass> construct(std::string id, Args&&... args)
    {
        return ObjectFactory<ObjectClass>::instance()->createObject(id, std::forward<Args>(args)...);
    }

    template<class ObjectClass>
    std::shared_ptr<ObjectClass> acquire(std::string id)
    {
        return ObjectFactory<ObjectClass>::instance()->getObject(id);
    }

    template<class ObjectClass>
    void destruct(std::string id)
    {
        ObjectFactory<ObjectClass>::instance()->deleteObject(id);
    }

    template<class ObjectClass>
    std::vector<std::string> objectList()
    {
        std::vector<std::string> keys;

        for(auto itr : ObjectFactory<ObjectClass>::instance()->objectMap)
        {
            keys.push_back(itr.first);
        }

        return keys;
    }
}

class Rectangle
{
    public:
        Rectangle(int w, int h) : width(w), height(h) {}

        void setVals(int w, int h)
        {
            width = w;
            height = h;
        }

        void getVals()
        {
            std::cout << width << 'x' << height << std::endl;
        }

    private:
        int width, height;
};

int main()
{
    auto myRectangle = TGE::construct<Rectangle>("MyRectangle", 5, 10);
    myRectangle->getVals();
    myRectangle->setVals(10, 5);
    TGE::acquire<Rectangle>("MyRectangle")->getVals();

    TGE::MyGame.destroy();
    return 0;
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2015-04-09 05:31:21

程序做得很好。

必须做

  1. FactoryBase添加虚拟析构函数。

建议

  1. 如果objectList()具有返回正确对象的函数(如ObjectFactory<ObjectClass>::getObjectList() ),则无需friend构造就可以很容易地实现ObjectFactory<ObjectClass>。返回ObjectFactory::instance()->getObjectList();}( template std::vector objectList() )
  2. 除了objectList()之外,大多数函数的名称都是一致的--使用一个动词作为第一个术语。应该更改为getObjectList()
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/86361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档