我最近使用我以前从未见过的技术在我们的产品中运行代码。我正在寻找参考,看看这是否是一种既定的技术(我不会把它称为模式),如果是这样,那么理解的风险和收益是什么。请注意,出于商业原因,我们不能使用C ++ 11构造。
下面的示例代码说明了该技术的一种用法。我们有两个从抽象基类派生的适配器,它定义了客户端要访问的通用API。
一个客户决定需要公开改编的班级。仅为此简单示例,客户端使用类型标记switch语句来发现类型。
为了实现,作者定义了抽象基类。在其中,他有一个嵌套的类模板,它包含一个纯虚拟的getter返回指向类型T的指针。他还有一个非虚拟的模板化方法,可以为所需的每种类型实例化(最好参考下面的例子)。
适配器派生自抽象基类,它是嵌套模板类。然后他们实现虚拟吸气剂。
客户端将知道适配类的类型,并可以使用适当的类型调用非虚拟模板化基类方法。这又调用了适配器类的模板方法。这里的主要目标似乎是让客户端免于使用dynamic_cast<>(),或者需要自己定义模板。
#include <iostream>
#include <string>
enum ObjectProxyType {
SimpleProxy,
CompoundProxy
};
class ObjectProxyIfc
{
protected:
ObjectProxyIfc() {}
public:
virtual ~ObjectProxyIfc() {}
virtual ObjectProxyType type() const = 0;
virtual std::string name() = 0;
// adapter method (example)
template<class T>
class ProxyGetterIfc
{
public:
virtual const T* get() const = 0;
};
template <typename T>
const T* get() const
{
// this templated method is non-virtual, and should not be
// overridden/shadowed by derived classes. Adapters will derive
// from ObjectProxyIfc *and*
// ObjectProxyIfc::ProxyGetterIfc<type-to-be-wrapped>, and then
// implement the wrapped virtual method, called here.
//
ProxyGetterIfc<T> *getter = dynamic_cast<ProxyGetterIfc<T> *>(const_cast<ObjectProxyIfc *>(this));
return getter ? getter->get() : 0;
}
};
class SimpleObject
{
public:
SimpleObject() {};
~SimpleObject() {};
std::string objName() const { return "SimpleObject"; }
};
class SimpleObjectProxy : public ObjectProxyIfc,
public ObjectProxyIfc::ProxyGetterIfc<SimpleObject>
{
public:
SimpleObjectProxy(SimpleObject *obj) : obj_(obj) {};
~SimpleObjectProxy() {};
virtual ObjectProxyType type() const { return SimpleProxy; }
virtual std::string name()
{
// adapter for wrapped object
return obj_->objName();
}
virtual const SimpleObject *get() const {
return obj_;
}
private:
SimpleObject *obj_;
};
ObjectProxyIfc *oPI()
{
return new SimpleObjectProxy(new SimpleObject());
}
class CompoundObject
{
public:
CompoundObject(const std::string &annotation) : annotation_(annotation) {};
~CompoundObject() {};
std::string objName() const { return "CompoundObject"; }
std::string annotation() const
{
// No adapter method is available for this item!
return annotation_;
}
private:
std::string annotation_;
};
class CompoundObjectProxy : public ObjectProxyIfc,
public ObjectProxyIfc::ProxyGetterIfc<CompoundObject *>
{
public:
CompoundObjectProxy(CompoundObject **objs) : objs_(objs) {};
~CompoundObjectProxy() {};
virtual ObjectProxyType type() const { return CompoundProxy; }
virtual std::string name()
{
// adapter for wrapped object
return objs_[0]->objName();
}
virtual CompoundObject *const *get() const {
return const_cast< CompoundObject *const *>(objs_);
}
private:
CompoundObject **objs_;
};
ObjectProxyIfc *oPI2()
{
CompoundObject *so = new CompoundObject("non-shared payload");
CompoundObject **sop = new (CompoundObject *);
*sop = so;
return new CompoundObjectProxy(sop);
}
void handleObj(ObjectProxyIfc *iObj)
{
switch (iObj->type())
{
case SimpleProxy: {
const SimpleObject *anObj = iObj->get<SimpleObject>();
std::cout << "Handling " << anObj->objName() << std::endl;
} break;
case CompoundProxy: {
CompoundObject *const *objs = iObj->get<CompoundObject *>();
const CompoundObject *anObj = *objs;
std::cout << "Handling " << anObj->objName() << "; " << anObj->annotation() << std::endl;
} break;
}
}
int main()
{
// common, adapted methods can be accessed from the base class for
// adapters, re: name()
//
ObjectProxyIfc *ptrOne = oPI();
std::cout << "First object is " << ptrOne->name() << std::endl;
// rarely, the client may need access to the data/methods in the
// wrapped object, which have no counterpart in the common subset
// implemented by the adapter. For this we go directly to the
// wrapped object.
//
handleObj(ptrOne);
ObjectProxyIfc *ptrTwo = oPI2();
std::cout << "Second object is " << ptrTwo->name() << std::endl;
handleObj(ptrTwo);
return 0;
}