2

我想为我的程序定义类似对象的插件。它们应该如下所示:

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和作为接口的具体实现。Prog2ViewProg3ViewSystemViewForSpecificModule

此外,我必须考虑以下情况:

Prog2 将嵌入 Prog1,我希望能够做到这一点:

  1. 实例化SpecificModule实例
  2. 运行调用的 prog1 部分SpecificModule::doSpecificTask();
  3. 运行也调用的 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 个解决方案之外的其他解决方案)?

4

0 回答 0