基于模板的自动注册工厂模式(C++11实现)

工厂类

factory.h

#pragma once

#include <functional>
#include <memory>
#include <unordered_map>

template <typename T, typename... Args>
class Factory {
 public:
  static Factory& Instance() {
    if (!instance_) {
      instance_ = new Factory<T, Args...>();
    }
    return *instance_;
  }

  void Register(const std::string& name,
                std::function<std::shared_ptr<T>(Args...)> creator) {
    creators_[name] = creator;
  }

  std::shared_ptr<T> Create(const std::string& name, Args... args) {
    return creators_.find(name) == creators_.end() ? std::shared_ptr<T>()
                                                   : creators_[name](args...);
  }

 private:
  Factory() {}
  static Factory<T, Args...>* instance_;
  std::unordered_map<std::string, std::function<std::shared_ptr<T>(Args...)>>
      creators_;
};

template <typename T, typename... Args>
Factory<T, Args...>* Factory<T, Args...>::instance_ = nullptr;

注册类

register.h

#pragma once

#include "factory.h"

template <typename Base, typename Impl, typename... Args>
class Register {
 public:
  explicit Register(const std::string& name) {
    Factory<Base, Args...>& factory = Factory<Base, Args...>::Instance();
    factory.Register(name, [](Args... args) {
      return std::shared_ptr<Base>(new Impl(args...));
    });
  }
};

基类

shoes.h

#pragma once

#include "factory.h"

class Shoes {
 public:
  explicit Shoes(const int& number) : number_(number) {};
  virtual void Message() = 0;
  virtual ~Shoes() = default;

 protected:
  const int number_;
};

typedef Factory<Shoes, int> ShoesFactory;

car.h

#pragma once

#include "factory.h"

class Car {
 public:
  explicit Car(const int& number, const std::string &size) : number_(number), size_(size) {};
  virtual void Message() = 0;
  virtual ~Car() = default;

 protected:
  const int number_;
  const std::string size_;
};

typedef Factory<Car, int, std::string> CarFactory;

派生类

nike.cc

#include <iostream>
#include "register.h"
#include "shoes.h"

class Nike : public Shoes {
 public:
  explicit Nike(const int& number) : Shoes(number) {}

  void Message() {
    std::cout << number_ << " Nike shoes !" << std::endl;
  }
};

namespace {
  Register<Shoes, Nike, int> _("nike"); // 注册该类,namespace{}防止变量"_"重复定义,.cc文件才会自动执行该语句,.h文件不执行
}

anta.cc

#include <iostream>
#include "register.h"
#include "shoes.h"

class Anta : public Shoes {
 public:
  explicit Anta(const int& number) : Shoes(number) {}

  void Message() {
    std::cout << number_ << " Anta shoes !" << std::endl;
  }
};

namespace {
  Register<Shoes, Anta, int> _("anta");
}

benz.cc

#include <iostream>
#include "register.h"
#include "car.h"

class Benz : public Car {
 public:
  explicit Benz(const int& number, const std::string &size) : Car(number, size) {}

  void Message() {
    std::cout << number_ << " " << size_ << " Benz car !" << std::endl;
  }
};

namespace {
  Register<Car, Benz, int, std::string> _("benz");
}

audi.cc

#include <iostream>
#include "register.h"
#include "car.h"

class Audi : public Car {
 public:
  explicit Audi(const int& number, const std::string &size) : Car(number, size) {}

  void Message() {
    std::cout << number_ << " " << size_ << " Audi car !" << std::endl;
  }
};

namespace {
  Register<Car, Audi, int, std::string> _("audi");
}

主函数

main.cc

#include "factory.h"
#include "shoes.h"
#include "car.h"

int main(int argc, char** argv) {
  auto nike_shoes = ShoesFactory::Instance().Create("nike", 1);
  if (nike_shoes) {
    nike_shoes->Message();
  }

  auto anta_shoes = ShoesFactory::Instance().Create("anta", 2);
  if (nike_shoes) {
    anta_shoes->Message();
  }

  auto benz_car = CarFactory::Instance().Create("benz", 1, "small");
  if (nike_shoes) {
    benz_car->Message();
  }

  auto audi_car = CarFactory::Instance().Create("audi", 2, "big");
  if (nike_shoes) {
    audi_car->Message();
  }

  return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(test)

set(CMAKE_CXX_STANDARD 11)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
 
add_executable(test main.cc factory.h register.h shoes.h nike.cc anta.cc car.h benz.cc audi.cc)

输出

1 Nike shoes !
2 Anta shoes !
1 small Benz car !
2 big Audi car !

猜你喜欢

转载自blog.csdn.net/A_L_A_N/article/details/114852146