一个可配置的对象工厂实现思路如下:
1 先注册可能需要创建对象的构造函数,将其放到一个内部关联容器map中,设置键为类型的名字,值为类型的构造函数。
2 然后在创建的时候根据类型名称查找对应的构造函数并最终创建出目标对象。
可配置的对象工厂如下:
#include <string>
#include <map>
#include <memory>
#include <functional>
using namespace std;
template<class T>
class IocContainer
{
public:
IocContainer() {}
~IocContainer() {}
// 注册需要创建对象的构造函数
template<class Drived>
void RegisterType(string strKey)
{
std::function<T*()> function = []{return new Drived();};
RegisterType(strKey, function);
}
// 根据唯一标识查找对应的构造函数,并创建指针对象
T* Resolve(string strKey)
{
if (m_creatorMap.find(strKey) == m_creatorMap.end())
{
return nullptr;
}
std::function<T*()> function = m_creatorMap(strKey);
return function();
}
// 创建智能指针对象
std::shared_ptr<T> ResolveShared(string strKey)
{
T* ptr = Resolve(strKey);
return std::shared_ptr<T>(ptr);
}
private:
void RegisterType(string strKey, std::function<T*()> creator)
{
if (m_creatorMap.find(strKey) != m_creatorMap.end()) {
throw std::invalid_argument("this key has already exist!");
}
m_creatorMap.emplace(strKey, creator);
}
private:
map<string, std::function<T*()>> m_creatorMap;
};
测试代码如下:
struct ICar
{
virtual ~ICar() {}
virtual void test() const = 0;
};
struct Bus : ICar
{
Bus() {};
void test() const { cout << "Bus::test()" << endl; };
};
struct Car : ICar
{
Car() {};
void test() const { cout << "Car::test()" << endl; };
};
int main()
{
IocContainer<ICar> carioc;
// Bus,ICar继承关系
carioc.RegisterType<Bus>("bus");
carioc.RegisterType<Car>("car");
std::shared_ptr<ICar> bus = carioc.ResolveShared("bus");
bus->test();
std::shared_ptr<ICar> car = carioc.ResolveShared("car");
car->test();
return 0;
}
输出结果:
Bus::test()
Car::test()
上述代码可以创建所有的无参数的ICar派生对象。但还有如下两点不足:
(1)只能创建无参对象,不能创建有参数的对象。
(2)只能创建一种接口类型ICar的对象,通过ioccar实例不能创建所有类型的对象。
如果希望能够创建所有类型的对象,则需要通过类型擦除来实现。