这个解决方案实际上对我有用,所以我把它放在这里作为答案:
PimpleHelper.h是一个 Pimpl 帮助器类,用于减少样板代码。使用 VendorFactory 实例化正确的供应商实现。多个供应商将注册他们实现给定接口的事实;对于给定的接口,只有一个供应商的实现被实例化。
#include <QSettings>
#include "VendorFactory.h"
#include <cxxabi.h>
// Pimpl Helper
template<typename T>
class PimplHelper
{
public:
PimplHelper()
{
m_interfaceNameImplemented = demangle(typeid(T).name());
initializeImpl();
}
T* getImpl()
{
return theImpl.data();
}
private:
QScopedPointer< T > theImpl;
QString m_interfaceNameImplemented;
void initializeImpl()
{
// Read in configuration
QSettings settings("AppSettings.ini", QSettings::IniFormat);
QString vendorToUse = settings.value("VENDOR_IMPLEMENTATION_KEY", "Vendor1").toString();
qDebug() << "Vendor to use is: " << vendorToUse << " Interface Implemented: " << m_interfaceNameImplemented;
// Obtain an instance of the vendor's class that implements the T interface
theImpl.reset(
VendorFactory<T>::create(vendorToUse, m_interfaceNameImplemented)
);
if(!theImpl)
qDebug() << "PimplHelper::initializeImpl, error resolving implementation for: "
<< vendorToUse << " Interface Implemented: " << m_interfaceNameImplemented;
}
const QString demangle(const char* name)
{
int status = -4;
char* res = abi::__cxa_demangle(name, NULL, NULL, &status);
const char* const demangled_name = (status==0)?res:name;
QString ret_val(demangled_name);
free(res);
return ret_val;
}
};
VendorFactory.h创建由不同供应商实现的类的实例。供应商通过宏向工厂注册他们的实现。
#include <QtCore>
template< class T>
class VendorFactory
{
private:
typedef T* (*CreateFunc)();
typedef QMap<QString, CreateFunc> FunctionMap;
public:
static T * create(const QString& vendorName, const QString& interfaceName)
{
typename FunctionMap::iterator it = creators()->find(vendorName + interfaceName);
if (it == creators()->end())
return NULL;
return (it.value())();
}
static bool reg(const QString& vendorName, const QString& interfaceName, CreateFunc fun)
{
qDebug() << "Registering: " << vendorName + interfaceName << endl;
creators()->insert(vendorName + interfaceName, fun);
return true;
}
static FunctionMap * creators()
{
static FunctionMap* creators = new FunctionMap;
return creators;
}
virtual ~VendorFactory() {}
};
/// @brief This registers a Vendor's class in the factory and adds a factory function named create_vendorImplClass()
/// and calls VendorFactory::reg() by the help of a dummy static variable to register the function.
/// @param vendorName A string representing the vendor's name
/// @param vendorImplClass The class implementing the interface given by the last parameter
/// @param interface The interface implemented by the vendorImplClass
#define REGISTER_IN_FACTORY( vendorName, vendorImplClass, interface ) \
namespace { \
interface* create_ ## vendorImplClass() { return new vendorImplClass; } \
static bool vendorImplClass ## _creator_registered = VendorFactory< interface >::reg( vendorName, # interface, create_ ## vendorImplClass); }
以下是它们的使用方式:
Person.h (面向公众的 API)
#include "IPerson.h"
#include "PimplHelper.h"
// Public facing API
class Person: public IPerson
{
public:
Person()
{
impl.reset( new PimplHelper<IPerson>());
}
QString GetFirstName();
QString GetLastName();
private:
QScopedPointer< PimplHelper<IPerson> > impl;
};
Person.cpp (面向公众的 API)
#include "Person.h"
QString Person::GetFirstName()
{ // I'd like to remove the call to getImpl() here
// and just use the overloaded -> operator, but it
// gives me a "has no member named GetFirstName()" error
return impl->getImpl()->GetFirstName();
}
QString Person::GetLastName()
{
return impl->getImpl()->GetLastName();
}
PersonImpl1.h包含 Vendor1 的实现
#include "IPerson.h"
#include "VendorFactory.h"
// Private Implementation
class PersonImpl1: public IPerson
{
public:
PersonImpl1():
FirstName("Jon"), LastName("Skeet")
{}
QString GetFirstName()
{
return FirstName;
}
QString GetLastName()
{
return LastName;
}
private:
QString FirstName;
QString LastName;
};
REGISTER_IN_FACTORY("Vendor1", PersonImpl1, IPerson)
PersonImpl2.h包含 Vendor2 的实现
#include "IPerson.h"
#include "VendorFactory.h"
// Private Implementation
class PersonImpl2: public IPerson
{
public:
PersonImpl2(): FirstName("Chuck"), LastName("Norris")
{}
QString GetFirstName()
{
return FirstName;
}
QString GetLastName()
{
return LastName;
}
private:
QString FirstName;
QString LastName;
};
REGISTER_IN_FACTORY("Vendor2", PersonImpl2, IPerson)
最后,main.cpp文件:
#include <QCoreApplication>
#include <QDebug>
#include "Person.h"
// The following needs to be included for the static/auto registration
// with the VendorFactory to occur. I'm not exactly sure why.
#include "PersonImpl1.h"
#include "PersonImpl2.h"
int main(int argc, char *argv[])
{
Q_UNUSED(argc)
Q_UNUSED(argv)
Person* p = new Person();
qDebug() << "The person implemented is: "
<< p->GetFirstName() << " " << p->GetLastName();
qDebug() << "exiting";
}
这是迄今为止对我有帮助的其他 SO 问题的列表:
从名称实例化类?
在编译时使用 C++ 模板在 AbstractFactory 中动态注册构造函数方法 在 C++
中的对象工厂实体/组件系统中注册对象创建者
,如何发现类型和构造组件?
有没有办法从保存类名的字符串中实例化对象?
静态变量未初始化
取消 std::type_info::name 的结果