我想为我的程序定义类似对象的插件。它们应该如下所示:
class ModuleBase
{
public :
void baseFunction1();
void baseFunction2();
...
virtual void init() = 0;
virtual void finalize() = 0;
};
class SpecificModule : public ModuleBase
{
public :
virtual void doSpecificTask() = 0;
};
因此,我将有 SpecificModule 实现:
class ConcreteSpecificModule1 : public SpecificModule
{
public :
void init();
void finalize();
void doSpecificTask();
};
为了掩盖实现和复杂性,我希望我的模块通过外观接口看到底层系统:
class SystemViewForSpecificModule
{
public :
virtual SystemData& getData(//some parameters) = 0;
virtual void doSystemAction1() = 0;
virtual void doSystemAction2() = 0;
...
};
最后,我希望能够制作几个可以处理模块和/或SpecificModule
实例的程序。
考虑到我有 prog1、prog2和prog3,我将不得不实现
Prog1View
和作为接口的具体实现。Prog2View
Prog3View
SystemViewForSpecificModule
此外,我必须考虑以下情况:
Prog2 将嵌入 Prog1,我希望能够做到这一点:
- 实例化
SpecificModule
实例 - 运行调用的 prog1 部分
SpecificModule::doSpecificTask();
- 运行也调用的 prog2 部分
SpecificModule::doSpecificTask();
我的问题是:如何在 SpecificModule 实例中传递/存储对系统的引用(或指针)?
1 - 在构建时存储参考:
因此SpecificModule 接口应该喜欢
class SpecificModule : public ModuleBase
{
SystemViewForSpecificModule& m_sys;
public :
SpecificModule(SystemViewForSpecificModule& sys):m_sys(sys){}
virtual void doSpecificTask() = 0;
};
这是解决我的问题的好方法,但不要忘记在 prog2 中我必须首先使用 prog1 运行我的模块,因此在这种情况下我必须动态地从 SystemViewForSpecificModule 实现切换。
- (+) 模块可以在其整个生命周期中访问系统,并且所有方法都可以访问它。
- (-) 参考设定后,不可更改
我们可以认为使用引用不是一个好的解决方案,或者使用这样的东西:
class SystemView : public SystemViewForSpecificModule
{
SystemViewForSpecificModule* concreteSystem;
public
SystemView(SystemViewForSpecificModule& sys)
{concreteSystem = &sys;}
void setSystem(SystemViewForSpecificModule& sys)
{concreteSystem = &sys;}
void doSystemAction1()
{concreteSystem->doSystemAction1();}
...
}
这样,模块甚至不知道实现已更改但是,我担心它会由于额外的 vtable 访问而降低性能。
2 - 使用setter指定系统视图
SpecificModule 接口应如下所示:
class SpecificModule : public ModuleBase
{
SystemViewForSpecificModule* m_sys;
public :
setSystem(SystemViewForSpecificModule& sys){m_sys = &sys;}
virtual void doSpecificTask() = 0;
};
这似乎是一个方便的解决方案,但我不喜欢该模块具有的事实:
- 知道这种变化
- 处理这个变化
- 在使用它之前检查指针的有效性
3 - 传递对 SpecificModule 方法的引用
至少SpecificModule
界面看起来像这样:
class SpecificModule : public ModuleBase
{
virtual void doSpecificTask(SystemViewForSpecificModule& sys) = 0;
};
我不喜欢将相同的引用 10000 次传递给同一个函数(prog1 和 prog2 部分都会多次调用它)。
此解决方案的另一个坏点是:我无权访问ModuleBase
方法中的系统视图(例如init()
和finalize()
)。显然,将它们移动到子类会降低继承的兴趣。
在这个示例案例中你会使用什么解决方案(我希望看到除了所提供的 3 个解决方案之外的其他解决方案)?