我有一个类,它有许多虚函数,允许您获取对接口的引用。使用我的API的客户端可以实现我的接口,然后使用他们的实现实现我的顶级接口IMyInterface。
我的代码然后作用于他们的多态IMyInterface实现。
下面是一些示例代码(不是真正的代码,但您可以了解其中的含义):
class MyImplementation : public IMyInterface
{
public:
virtual Interface1& get1()
{
return impl1
}
virtual Interface2& get2()
{
return impl2;
}
// etc...
public:
Impl1 impl1;
Impl2 impl2;
// etc...
};
我认为这个设计看起来真的很好,但是有一天我想改变其中一个实现,但是只有一个。在这种情况下,我必须重写整个类并复制大量代码。
实际上有6个Impl对象,所以我必须重写一个类,它具有完全相同的5个Impl对象,但有一个不同。
另一个问题是人们依赖于这个API设计,所以我需要保留它的基础。
是否有一种方法来修改设计,使其更灵活,同时仍然保持这个API?
我从你的问题中了解到:
如果我理解正确的话,您正在使用或多或少的类和基本组件的汇编,并且您希望能够以最少的编码交换组件。
备选方案1:动态装配
为什么不在构造时选择动态组装呢:
class MyBase : public IMyInterface
{
public:
Interface1& get1() { return *pimpl1; }
Interface2& get2() { return *pimpl2; }
//...
Interfacen& getn() { return *pimpln; }
protected:
MyBase (unique_ptr<Interface1> p1,
unique_ptr<Interface2> p2,
/*...*/
unique_ptr<Interfacen> pn) : // constructor assembles parts
pimpl1(move(p1)),pimpl2(move(p2)),/*...*/pimpln(move(pn)) {}
private:
unique_ptr<Interface1> pimpl1; // implemented with unique ptr for greater safety
unique_ptr<Interface2> pimpl2;
//...
unique_ptr<Interfacen> pimpln;
};
使用这样的逻辑,您的派生类看起来像:
class MyImplementationX : public MyBase {
public:
MyImplementationX() : MyBase(make_unique<Impl1>(), make_unique<Impl2>(), /*...*/ make_unique<Impln>()) {}
};
class MyImplementationY : public MyBase {
public:
MyImplementationX() : MyBase(make_unique<Impl1>(), make_unique<Impl2b>(), /*...*/ make_unique<Impln>()) {}
};
选项2:编译时汇编
您可以通过使用模板来摆脱运行时程序集,额外的分配和智能指针:
template <class I1, class I2, /*...*/ class IN,
class M1, class M2, /*...*/ class M3>
class MyBase {
public:
I1& get1() { return m1; }
I2& get2() { return m2; }
...
private:
M1 m1;
M2 m2;
...
};
顺便说一下,关于这种设计有一本很好的书:a . alexandrescu的《现代c++设计》,作者在书中提出了一种"基于策略的设计"(策略是用模板实现的策略模式)。