There are some business logic. You need to manage multiple objects of the same type and provide interfaces such as query and deletion. In these scenarios, you can call the Managed Objects Entity, the classes that manage Entity are naturally called Entity_Manager. When a hierarchical object is organized in this way, it is intuitive and the style of the Project is unified. Once everyone is familiar with this method, it is easy to understand the Entity_Manager written by others. Based on my previous project experience, I implemented the Entity and Entity_Manager classes by myself. The Code is as follows:
# Ifndef _ ENTITY_H _ # define _ ENTITY_H _ # include <string> # include <map> typedef unsigned int uint32; class Entity {protected: Entity () {m_id = 0;} public: virtual ~ Entity () {} void id (uint32 _ id) {m_id = _ id;} uint32 id () const {return m_id;} void name (std: string _ name) {m_name = _ name;} std: string name () const {return m_name;} private: uint32 m_id; std: string m_name ;}; // callback template <typename Concrete_Entity> class Entity_Exec {public: Entity_Exec () {} virtual ~ Entity_Exec () {} virtual bool exec (Concrete_Entity * entity) = 0; virtual bool can_delete (Concrete_Entity * entity) const {return true ;}; class Guard_Ref {public: guard_Ref (bool & val): m_val (val) {m_val = true ;}~ Guard_Ref () {m_val = false;} bool & m_val;}; template <typename Key> class Entity_Map {protected: Entity_Map () {m_in_iteration = false ;}~ Entity_Map () {}// whether the iteration is in progress. It is used to prohibit operations such as bool in_iteration () const {return m_in_iteration;} bool add_entity (Key key Key, entity * entity) {if (in_iteration () {return false;} if (m_entity_map.find (key )! = M_entity_map.end () {return false;} m_entity_map [key] = entity; return true;} Entity * get_entity (Key key) const {typename std: map <Key, entity * >:: const_iterator iter = m_entity_map.find (key); if (iter = m_entity_map.end () {return NULL;} return iter-> second;} uint32 size () const {return m_entity_map.size ();} bool empty () const {return m_entity_map.empty ();} void clear () {if (! In_iteration () {entity () ;}} template <typename Concrete_Entity> void exec_all (Entity_Exec <Concrete_Entity> & cb) {Guard_Ref guard (entity); for (typename std :: map <Key, Entity * >:: iterator iter = m_entity_map.begin (); iter! = M_entity_map.end (); ++ iter) {cb.exe c (static_cast <Concrete_Entity *> (iter-> second ));}} template <typename Concrete_Entity> bool exec_until (Entity_Exec <Concrete_Entity> & cb) {Guard_Ref guard (m_in_iteration); for (typename std: map <Key, Entity *> :: iterator iter = m_entity_map.begin (); iter! = M_entity_map.end (); ++ iter) {if(cb.exe c (static_cast <Concrete_Entity *> (iter-> second) {return true ;}} return false ;} template <typename Concrete_Entity> bool exec_if (Entity_Exec <Concrete_Entity> & cb) {bool ret = false; Guard_Ref guard (m_in_iteration); for (typename std: map <Key, entity *>: iterator iter = m_entity_map.begin (); iter! = Encrypt (); ++ iter) {Concrete_Entity * concrete_entity = static_cast <Concrete_Entity *> (iter-> second); if(cb.exe c (concrete_entity) {ret = true ;}} return ret;} void delete_entity (Key key Key) {if (! In_iteration () {m_entity_map.erase (key) ;}} template <typename Concrete_Entity> bool delete_if (Entity_Exec <Concrete_Entity> & cb, std: vector <Entity *> & del_vec) {if (in_iteration () {return false;} Guard_Ref guard (m_in_iteration); bool ret = false; for (typename std: map <Key, Entity *> :: iterator iter = m_entity_map.begin (); iter! = M_entity_map.end (); ++ iter) {Concrete_Entity * concrete_entity = static_cast <Concrete_Entity *> (iter-> second); if (cb. can_delete (concrete_entity) {ret = true; del_vec.push_back (concrete_entity) ;}return ret ;}private: std: map <Key, Entity *> m_entity_map; bool m_in_iteration ;}; class KEY_UINT32: protected Entity_Map <uint32> {protected: typedef Entity_Map <uint32> Super; KEY_UINT32 () {} bool Add_entity (Entity * entity) {return Super: add_entity (entity-> id (), entity);} void delete_entity (Entity * entity) {Super :: delete_entity (entity-> id () ;}; class KEY_STRING: protected Entity_Map <std: string >{ protected: typedef Entity_Map <std: string> Super; KEY_STRING () {} bool add_entity (Entity * entity) {return Super: add_entity (entity-> name (), entity);} void delete_entity (Entity * entity) {Super: delete_entity (entity-> name () ;}; // placeholder template <int> class KEY_NONE {protected: KEY_NONE () {} void clear () {} bool add_entity (Entity * entity) {return true;} void delete_entity (Entity * entity ){}}; // extract the trait template <typename T> struct Get_Super {}; template <> struct Get_Super <uint32> {typedef KEY_UINT32 Super ;}; template <> struct Get_Super <std:: string> {typedef KEY_STRING Super ;}; template <typename Concrete_Entity, typename Super1, typename Super2 = KEY_NONE <1> class Entity_Manager: private Super1, private Super2 {protected: Entity_Manager () {} bool add_entity (Entity * entity) {if (! Super1: add_entity (entity) {return false;} if (! Super2: add_entity (entity) {Super1: delete_entity (entity); return false;} return true;} bool delete_if (Entity_Exec <Concrete_Entity> & cb) {std :: vector <Entity *> del_vec; if (! Super1: delete_if (cb, del_vec) {return false;} for (std: vector <Entity * >:: iterator iter = del_vec.begin (); iter! = Del_vec.end (); ++ iter) {Concrete_Entity * concrete_entity = static_cast <Concrete_Entity *> (entity); delete_entity (entity); cb.exe c (concrete_entity);} return true ;} void delete_all (Entity_Exec <Concrete_Entity> & cb) {exec_all (cb); clear () ;}template <typename Key> Concrete_Entity * get_entity (Key key Key) const {return static_cast <Concrete_Entity *> (Get_Super <Key >:: Super: get_entity (key);} void delete_entity (Entity * entity) {Super1 :: delete_entity (entity); Super2: delete_entity (entity);} public: uint32 size () const {return Super1: size ();} bool empty () const {return Super1:: empty ();} void clear () {Super1: clear (); Super2: clear ();} bool exec_until (Entity_Exec <Concrete_Entity> & cb) {return Super1:: exec_until (cb);} bool exec_if (Entity_Exec <Concrete_Entity> & cb) {return Super1: exec_if (cb);} void exec_all (Entity_Exec <Concrete_Entity> & cb) {Super1: exec_all (cb );}};
# Endif my Entity_Manager supports two types of indexes to find managed objects, one is by name, and the other is by Number id, the specific function module can inherit Entity_Manager from different template parameters as needed to manage its own objects. Here is a simple example to illustrate how to use the Entity_Manager class. If there are many tasks in the project, you need to create a Task manager to manage the tasks. We can abstract the tasks into Task classes, the task manager is abstracted as the Task_Manager class. If I want to manage my tasks by id, The Task_Manager class is defined as follows:
class Task_Manager : public Entity_Manager<Task, KEY_UINT32> { public: Task* get_task(uint32 task_id) const { return get_entity(task_id); } bool add_task(const Task *task) { return add_entity(task); } void delete_task(const Task *task) { delete_entity(task); } void print_all_task_name() { struct CB : Entity_Exec<Task> { bool exec(Task *task) { print(task->name()); } } CB cb; exec_all(cb); } };
After inheriting the Entity_Manager class, the Task_Manager class can manage multiple Task classes and support query, deletion, and traversal of tasks, in addition, a protection mechanism is implemented in the base class of Entity_Manager, that is, during iteration, operations that will not cause the iterator to fail, so in the development of business functions, you can boldly use the Entity_Manger management class. If the project uses management-level objects in the same way, the style of the project is very uniform, and every developer in the project can understand the manager written by others as quickly as possible, which is also of great benefit to the project. Therefore, you are welcome to use the Entity_Manager class in your project !!!