#pragma once #include #include #include #include "common/log/log.h" namespace common { template class AbstractFactory { public: virtual ~AbstractFactory() = default; virtual BaseClass *Create() = 0; }; template class ConcreteFactory : public AbstractFactory { public: BaseClass *Create() override { return new DerivedClass; } }; template inline auto &GetFactoryMap() { static std::map>> map; return map; } template class Registerer { public: template static void Register(const std::string &derived_class_name) { static_assert(std::is_base_of::value, ""); auto &factory_map = GetFactoryMap(); if (factory_map.find(derived_class_name) != factory_map.end()) { return; } factory_map[derived_class_name].reset( new ConcreteFactory); } static BaseClass *NewInstance(const std::string &derived_class_name) { auto &factory_map = GetFactoryMap(); auto iter = factory_map.find(derived_class_name); if (iter == factory_map.end()) { AFATAL << "Class not registered: " << derived_class_name << "."; return nullptr; } return iter->second->Create(); } static bool IsRegistered(const std::string &derived_class_name) { auto &factory_map = GetFactoryMap(); return factory_map.find(derived_class_name) != factory_map.end(); } }; } // namespace common #define REGISTER_CLASS(base_class, derived_class) \ namespace { \ __attribute__((constructor)) void Register##derived_class() { \ ::common::Registerer::Register(#derived_class); \ } \ } // namespace