How to implement the factory method pattern in C++ correctly

后端 未结 11 1177
暗喜
暗喜 2020-11-22 14:55

There\'s this one thing in C++ which has been making me feel uncomfortable for quite a long time, because I honestly don\'t know how to do it, even though it sounds simple:<

11条回答
  •  遥遥无期
    2020-11-22 15:09

    This is my c++11 style solution. parameter 'base' is for base class of all sub-classes. creators, are std::function objects to create sub-class instances, might be a binding to your sub-class' static member function 'create(some args)'. This maybe not perfect but works for me. And it is kinda 'general' solution.

    template  class factory {
    public:
      factory() {}
      factory(const factory &) = delete;
      factory &operator=(const factory &) = delete;
    
      auto create(const std::string name, params... args) {
        auto key = your_hash_func(name.c_str(), name.size());
        return std::move(create(key, args...));
      }
    
      auto create(key_t key, params... args) {
        std::unique_ptr obj{creators_[key](args...)};
        return obj;
      }
    
      void register_creator(const std::string name,
                            std::function &&creator) {
        auto key = your_hash_func(name.c_str(), name.size());
        creators_[key] = std::move(creator);
      }
    
    protected:
      std::unordered_map> creators_;
    };
    

    An example on usage.

    class base {
    public:
      base(int val) : val_(val) {}
    
      virtual ~base() { std::cout << "base destroyed\n"; }
    
    protected:
      int val_ = 0;
    };
    
    class foo : public base {
    public:
      foo(int val) : base(val) { std::cout << "foo " << val << " \n"; }
    
      static foo *create(int val) { return new foo(val); }
    
      virtual ~foo() { std::cout << "foo destroyed\n"; }
    };
    
    class bar : public base {
    public:
      bar(int val) : base(val) { std::cout << "bar " << val << "\n"; }
    
      static bar *create(int val) { return new bar(val); }
    
      virtual ~bar() { std::cout << "bar destroyed\n"; }
    };
    
    int main() {
      common::factory factory;
    
      auto foo_creator = std::bind(&foo::create, std::placeholders::_1);
      auto bar_creator = std::bind(&bar::create, std::placeholders::_1);
    
      factory.register_creator("foo", foo_creator);
      factory.register_creator("bar", bar_creator);
    
      {
        auto foo_obj = std::move(factory.create("foo", 80));
        foo_obj.reset();
      }
    
      {
        auto bar_obj = std::move(factory.create("bar", 90));
        bar_obj.reset();
      }
    }
    

提交回复
热议问题