在整个应用程序中重用接口

时间:2010-09-24 16:08:37

标签: c++ interface modularity

我目前正忙着在我的应用程序中重构大部分内容。主要目的是尽可能地删除不同模块之间的依赖关系。我现在偶然发现以下问题:

在我的应用程序中,我有一个GUI模块,它定义了一个接口IDataProvider。接口需要由应用程序实现,并用于向GUI模块“提供数据”。例如。可以为此IDataProvider提供数据网格,并使用它来遍历应在数据网格中显示的所有实例,并获取其数据。

现在有另一个模块(实际上还有更多模块),它们都需要类似的东西(如报告模块,数据库集成模块,数学求解器模块......)。在这一刻,我可以看到我能做的两件事:

  • 我可以将IDataProvider从GUI层移动到更低级别的层,并在所有其他模块中重用相同的接口。
    • 这样做的好处是应用程序可以更轻松地使用所有模块(它只需要实现一次数据提供程序)。
    • 缺点是我在模块和中央IDataProvider之间引入了依赖关系。如果有人开始使用一个模块所需的其他方法扩展IDataProvider,它也会开始污染其他模块。
  • 另一种方法是为每个模块提供自己的数据提供程序,如果要使用所有模块,则强制应用程序实现所有模块。
    • 优点是模块不依赖于公共部分
    • 缺点是我最终得到IGridDataProvider,IReportDataProvider,IDatabaseDataProvider,ISolverDataProvider。

最好的使用方法是什么?如果它们需要[几乎或完全]相同类型的接口,是否可以使所有模块依赖于相同的公共接口?

如果我使用相同的IDataProvider界面,将来是否会出现令人讨厌的问题(目前我还不知道)?

4 个答案:

答案 0 :(得分:1)

如果您担心其他方法将应用于接口,则可以使用适配器模式。那就是:

class myFoo{
public:
    Bar getBar() =0;
}

在另一个模块中:

class myBaz{
public:
    Bar getBar() =0;
}

然后使用另一个:

class MyAdaptor: public myBaz{
public:
    MyAdaptor(myFoo *_input){
        m_Foo = _input;
    }

    Bar getBar(){ return m_Foo->getBar(); }

private:
    myFoo* m_Foo;
}

通过这种方式,您可以在myBaz界面中实现所有内容,只需在一个位置提供粘合剂。 myFoo可以根据需要添加任意数量的附加方法,其余的应用程序无需了解或关注它。

答案 1 :(得分:1)

您可以选择将IDataProvider移动到较低级别的层次。

需要扩展接口的模块可以将这些扩展放在IDataProvider自己的子接口中。您可以通过主动创建这些子接口来鼓励这一点。

答案 2 :(得分:1)

我不介意拥有多个模块,具体取决于一个接口,即使它不使用接口发布的所有方法。你也可以在界面的一部分意义上考虑更多,而不是为了它的意图。您提到的大多数模块只需要读取权限。所以你可以用这种方式分开并有另一个用于写等等。

数据层不需要知道数据的用途(这是表示层的工作)。它只需要知道如何返回它以及如何修改它。

此外,将数据提供程序(也可以标记为控制器)移动到较低级别绝对没有问题,因为它可能已经实现了一些与UI无关的业务逻辑(如数据一致性)。

答案 3 :(得分:1)

为什么不进行中间实施?让一些类在一个分解库(或其他层)中实现IDataProvider的重复部分(如第一种情况)。此外,每个人都需要“实施”他们自己的IDataProvider(如第二种情况)。然后,您可以在整个地方重复使用IDataProvider实现,并通过创建派生类在自定义类中添加特定方法...

即:

    // Common module.
class BasicDataProvider : IDataProvider
{
public:
    // common overrides...
};

    // For modules requiring no specific methods...
typedef BasicDataProvider ReportDataProvider;

    // Database module requires "special" handling.
class DatabaseDataProvider : BasicDataProvider
{
public:
    // custom overrides...
};