前言
使用工厂模式时,需要将类注册进工厂里,看到一种新的奇技淫巧,使用静态变量来将类注册进工厂。
代码
Product.h
#ifndef PRODUCT_H
#define PRODUCT_Hclass Product
{
public:Product(){};virtual ~Product(){};virtual void doWork() = 0;
};
#endif // PRODUCT_H
Factory.h
#ifndef FACTORY_H
#define FACTORY_H#include <map>
#include <stdexcept>
#include <string>
#include <functional>
#include <memory>
#include "Product.h"#define REGISTER_FACTORY_VNAME(T) reg_msg_##T##_
#define REGISTER_FACTORY(T, ...) static Factory::register_str<T> REGISTER_FACTORY_VNAME(T)(#T, ##__VA_ARGS__);
#define REGISTER_FACTORY_NAME(T, key, ...) static Factory::register_str<T> REGISTER_FACTORY_VNAME(T)(key, ##__VA_ARGS__);class Factory
{
public:template<typename T>struct register_str{register_str(const std::string& key){Factory::get().map_.emplace(key, [] { return new T(); });}template<typename... Args>register_str(const std::string& key, Args... args){Factory::get().map_.emplace(key, [&] { return new T(args...); });}};static Product* produce(const std::string& key);static std::unique_ptr<Product> produceUnique(const std::string& key);static std::shared_ptr<Product> produceShared(const std::string& key);private:Factory();Factory(const Factory&) = delete;Factory(Factory&&) = delete;static Factory& get(){static Factory instance;return instance;}static std::map<std::string, std::function<Product*()>> map_;
};
#endif // FACTORY_H
Factory.cpp
#include "Factory.h"std::map<std::string, std::function<Product*()>> Factory::map_;Product *Factory::produce(const std::string &key)
{if (map_.find(key) != map_.end())return map_[key]();elsereturn nullptr;
}std::unique_ptr<Product> Factory::produceUnique(const std::string &key)
{return std::unique_ptr<Product>(produce(key));
}std::shared_ptr<Product> Factory::produceShared(const std::string &key)
{return std::shared_ptr<Product>(produce(key));
}Factory::Factory() {}
以上就是产品基类 和 工厂代码。
特例化产品
MyProduct.h
#ifndef MYPRODUCT_H
#define MYPRODUCT_H#include "Product.h"class MyProduct1 : public Product
{
public:MyProduct1();virtual ~MyProduct1(){};virtual void doWork();
};class MyProduct2 : public Product
{
public:MyProduct2();virtual ~MyProduct2(){};virtual void doWork();
};
#endif // MYPRODUCT_H
MyProduct.cpp
#include "MyProduct.h"
#include <QDebug>
#include "Factory.h"REGISTER_FACTORY(MyProduct1);
REGISTER_FACTORY_NAME(MyProduct2, "MyProduct2");
MyProduct1::MyProduct1() {}void MyProduct1::doWork()
{qDebug()<<"MyProduct1::doWork";
}MyProduct2::MyProduct2()
{}void MyProduct2::doWork()
{qDebug()<<"MyProduct1::doWork";
}
我们看看 REGISTER_FACTORY_NAME(MyProduct2, “MyProduct2”); 这个宏做了什么。
将宏展开后是
static Factory::register_str<MyProduct2> reg_msg_MyProduct2_("MyProduct2");
是声明了全局静态变量 reg_msg_MyProduct2_,类型是 Factory::register_str。这样 reg_msg_MyProduct2_ 初始化时就会调用 register_str 的构造函数
register_str(const std::string& key){Factory::get().map_.emplace(key, [] { return new T(); });}
将 new 函数放进 Factory 的 map_ 中,这样就能使用 特定字符串来从工厂里 new一个新对象出来。
使用方式
#include "Factory.h"
#include "MyProduct.h"int main(int argc, char *argv[])
{Product* p = Factory::produce("MyProduct1");p->doWork();auto p2 = Factory::produceUnique("MyProduct2");p2->doWork();auto errorPtr = Factory::produceUnique("MyProduct");if(errorPtr != nullptr){errorPtr->doWork();}
}