前言
使用工厂模式时,需要将类注册进工厂里,看到一种新的奇技淫巧,使用静态变量来将类注册进工厂。
代码
Product.h
#ifndef PRODUCT_H
#define PRODUCT_H
class 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]();
else
return 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();
}
}