I'm working on a framework that will be used to create simple 2D grid based games. It is using an Entity-Component-System pattern with corresponding manager classes used to control the lifespan of objects and construct them polymorphically based on an ID.In addition to general improvements to my code, I'm asking for feedback on the implementation of the ECS model specifically. Things I would like to change are:Remove Manager classes (if possible)Decouple Systems and Components keys from base classes (related post).I don't like the use of my manager classes, I created them out of necessity to ensure the proper constructors are called on my abstract base classes, and would like to redesign the framework without them if possible.I would appreciate any advice on decoupling the Systems and Components id's from their base classes. (Possibly create a generic key class that can be used for both base classes?) Related post.Using the ECS:SystemsManager* sysMan = new ConcreteSystemsManager();EntitiesManager* entMan = new ConcreteEntitiesManager();sysMan->createSystem(ExampleSystem);entMan->createEntity(ExampleEntity);sysMan->getSystemPtr(ExampleSystem)->registerEntity(    entMan->getEntityPtr(ExampleEntity);GameState* gameState = new ConcreteGameState(entMan, sysMan);gameState->run();I've only included the declarations of the classes used in my framework, I didn't feel it was necessary since my request for feedback is about my overall design, however I'll post the implementation files upon request.State.hpp#pragma once#include EntitiesManager.hpp#include SystemsManager.hppnamespace drj{namespace gfw{namespace core{    // Forward Declarations    class GameSystem;    // Base class for concrete GameState classes to    // inherit from.    class State    {    public:        State();        State(EntitiesManager*, SystemsManager*);        ~State();        void setEntitiesManager(EntitiesManager*);        void setSystemsManager(SystemsManager*);        virtual int run() = 0;    protected:    private:        std::shared_ptr<EntitiesManager> entitiesManager;        std::shared_ptr<SystemsManager> systemsManager;    };};};};IManager.hpp#pragma oncenamespace drj{namespace gfw{namespace core{    class IManager    {    public:        virtual ~IManager();        virtual int create(std::string const&) = 0;        virtual int destroy(std::string const&) = 0;    protected:        IManager();    private:    };};};};EntitiesManager.hpp#pragma once#include <string>#include <memory>#include <unordered_map>#include Entity.hpp#include IManager.hppnamespace drj{namespace gfw{namespace core{    class EntitiesManager : public IManager    {    public:        EntitiesManager();        virtual ~EntitiesManager();        // Returns nullptr if the entity doesn't exist.        // This EntitiesManager still owns the pointer.        Entity* getEntityPtr(std::string const&) const;        // Returns -1 if the entity already exists.        int create(std::string const&);        // Returns -1 if the entity didn't exist.        int destroy(std::string const&);    protected:          private:        std::unordered_map<            std::string,            std::unique_ptr<Entity>> entities;    };};};};SystemsManager.hpp#pragma once#include <string>#include <memory>#include <unordered_map>#include System.hpp#include IManager.hppnamespace drj{namespace gfw{namespace core{    class SystemsManager : public IManager    {    public:        virtual ~SystemsManager();        // Returns nullptr if the system doesn't exist.        System* getSystemPtr(std::string const&) const;        // Returns -1 if the system already exists.        virtual int create(std::string const&) = 0;        // Returns -1 if the system didn't exist.        virtual int destroy(std::string const&) = 0;    protected:        SystemsManager();    private:        std::unordered_map<            std::string,            std::unique_ptr<System>> systems;    };};};};ComponentsManager.hpp#pragma once#include <string>#include <memory>#include <unordered_map>#include Component.hpp#include IManager.hppnamespace drj{namespace gfw{namespace core{    class ComponentsManager : public IManager    {    public:        virtual ~ComponentsManager();        // Returns nullptr if the component doesn't exist.        Component* getComponentPtr(std::string const&) const;        // Returns -1 if the component already exists.        virtual int create(std::string const&) = 0;        // Returns -1 if the component didn't exist.        virtual int destroy(std::string const&) = 0;    protected:        ComponentsManager();        std::unordered_map<            std::string,            std::unique_ptr<Component>> components;    private:    };};};};Entity.hpp#pragma once#include <list>#include <memory>#include <string>#include ComponentsManager.hpp//#include GameComponent.hpp#include System.hppnamespace drj{namespace gfw{namespace core{    // GameObjects are used as Entities in the ECS model    // of the core GameEngine module.    class Entity    {        friend class System;    public:        Entity();        ~Entity();        // Returns true if the provided key is in this        // objects systemsRegistry.        bool hasSystemKey(std::string const&) const;        // Adding a key is not the same as registering        // an entity, however it is a process in that.        void addSystemKey(std::string const&);        void removeSystemKey(std::string const&);        ComponentsManager* getComponentsManager() const;        void setComponentsManager(ComponentsManager*);    protected:    private:        std::list<std::string> systemsRegistry;        std::unique_ptr<ComponentsManager> componentsManager;    };};};};Component.hpp#pragma once#include <string>#include <list>namespace drj{namespace gfw{namespace core{    // Base class for specialized GameComponent    // classes to inherit from.    class Component    {        friend class System;    public:        std::string const& getKey() const;        virtual ~Component();    protected:        Component(std::string const&);    private:        Component();        std::list<std::string> systemsUsing;        const std::string key;        size_t getSystemsUsingSize() const;        bool hasSystemKey(std::string const&) const;        // Used by GameSystem when registering        // entities and components.        void addSystemKey(std::string const&);        void removeSystemKey(std::string const&);    };};};};System.hpp#pragma once#include <string>#include Component.hppnamespace drj{namespace gfw{namespace core{    // Forward Declarations    class Entity;    // Base class used to create specialized Systems    // that use registered GameObjects as their    // input and output data.    class System    {    public:        virtual ~System();        std::string const& getKey() const;        // Returns true if the provided entity        // has this systems key in its systemsRegistry.        //        // The same as calling GameObject::hasKey(GameSystem::key)        bool isRegistered(Entity const&) const;        // Adds this systems key to the provided        // entities systemsRegistry and adds the        // necessary components to its ComponentsManager.        void registerEntity(Entity&) const;        void unregisterEntity(Entity&) const;        virtual int run(Entity&) = 0;    protected:        // Prevents users from creating non-specialized        // GameSystem objects.        //        // @arg[0] The key used to identify this        // system apart from other systems.        //        // @arg[1] The list of component keys that        // are required for concrete systems.        System(std::string const&,            std::list<std::string> const&);    private:        System();        const std::list<std::string> componentsRegistry;        const std::string registryKey;    };};};};
An ECS model for game development
c++;design patterns;game;c++11;entity component system