高级语言里如java有反射,可以根据类名动态生成类实例;也可以动态获取类成员变量和函数。
Poco里是否有类似功能呢? 对于前者,根据类名动态生成类实例。Poco提供了类似的功能。
它就是模板类DynamicFactory
它的原理很简单,通过注册名字,将名字与类型储存在map中。使用的时候根据名字找寻对应的类型,然后生成该类型的实例。
我们来看一下使用。 定义两个类A,B都集成基类Base
class Base
{
public:
Base()
{
}
virtual ~Base()
{
}
};
class A: public Base
{
};
class B: public Base
{
};
使用Dynamic注册
DynamicFactory<Base> dynFactory;
dynFactory.registerClass<A>("A");
dynFactory.registerClass<B>("B");
assert (dynFactory.isClass("A"));
assert (dynFactory.isClass("B"));
assert (!dynFactory.isClass("C"));
std::unique_ptr<A> a(dynamic_cast<A*>(dynFactory.createInstance("A")));
std::unique_ptr<B> b(dynamic_cast<B*>(dynFactory.createInstance("B")));
try{
dynFactory.registerClass<A>("A");
fail("already registered - must throw");
}
catch (Poco::ExistsException&)
{
}
dynFactory.unregisterClass("B");
assert (dynFactory.isClass("A"));
assert (!dynFactory.isClass("B"));
try
{
std::unique_ptr<B> b(dynamic_cast<B*>(dynFactory.createInstance("B")));
fail("unregistered - must throw");
}
catch (Poco::NotFoundException&)
{
}
DynamicFactory的模板是基类类型,注册时使用子类类型。
看一下源码的实现原理。
在DynamicFactory中定义了实现工厂的接口AbstractInstantiator,然后在map中存储名字和AbstractInstantiator键值对。就这么简单!
template <class Base>
class DynamicFactory
{
public:
// 定义了抽象方法
typedef AbstractInstantiator<Base> AbstractFactory
private:
typedef std::map<std::string, AbstractFactory*> FactoryMap;
FactoryMap _map; // 基本原理就是将类名称和类型存储在map中
mutable FastMutex _mutex;
}
那么AbstractFactory是什么呢?说白了,它就是一个接口,定义了行为。
template <class Base>
class AbstractInstantiator
{
// 通过该接口定义实现实例,返回基类指针
virtual Base* createInstance() const = 0;
}
具体的类是Instantiator,跟AbstractFactory定义在一起。
template <class C, class Base>
class Instantiator: public AbstractInstantiator<Base>
{
public:
// 哦,原来如此。就这么简单
Base* createInstance() const
{
return new C;
}
}
所以从源码上来看,DynamicFactory中的模板类跟注册类可以是继承关系,也可以是同一个类型。
网友评论