0

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

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

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

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

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

如果我使用相同的 IDataProvider 接口,这是否会在未来产生令人讨厌的问题(我目前不知道)?

4

4 回答 4

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需要添加任意数量的附加方法,应用程序的其余部分不需要知道或关心它。

于 2010-09-24T16:13:26.643 回答
1

您引用的将 IDataProvider 移动到较低级别层的缺点有另一种选择。

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

于 2010-09-24T16:13:33.160 回答
1

我不介意有多个模块依赖于一个接口,即使它不使用接口发布的所有方法。您还可以更多地考虑接口的一部分的含义,而不是它打算使用的模块。您提到的大多数模块只需要读取权限。因此,您可以以这种方式分开并有另一个用于写入等。

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

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

于 2010-09-24T16:17:30.843 回答
1

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

IE:

    // 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...
};
于 2010-09-24T16:55:56.260 回答