【问题标题】:How to write interfaces to handle disparate concepts如何编写接口来处理不同的概念
【发布时间】:2025-11-25 23:30:02
【问题描述】:

我一直难以理解如何抽象接口以包含它们的整体效果,但仍要处理细节:

例如,

interface iAudio 
{
    iInput input;
}

iInput 可以是来自各种事物(声卡、文件等)的输入。

iAudio 不关心输入来自哪里,只要它可以获取数据。所以 iInput 抽象了输入。到目前为止我很好。我可以有不同的东西来实现 iInput 插入,但似乎很难弄清楚在这之后要做什么。

我显然可以编写像if (input is InputFile) ... 这样的代码,但这似乎适得其反。 (但这对我来说是有意义的方式)

我知道但对我来说似乎很难的另一种方法是尝试让 iInput 有适当的方法来获取数据,例如,

interface iInput
{
    byte[] GetData();
}

然后让不同的类实现这个,例如 InputFile 或 InputSoundcard。虽然它看起来太抽象了,并且没有提供很多做任何事情的能力。 (也许我可以获取数据,但使用 InputFile 我需要指定文件名,而 InputSoundcard 将是其他设备特定信息。那么,我最终仍将使用第一种情况。

也许这基本上是正确的做法?感觉不对。希望我的示例足够清晰,可以证明问题所在。

【问题讨论】:

    标签: oop interface


    【解决方案1】:

    您想要这样的界面的原因是因为音频代码不需要关心输入的类型。

    没有消失,但它在那个类之外。

    在某些时候,有一些代码选择了一些输入,但并未全部与音频代码混淆。

    更新:

    确实有很多方法可以设计特定的应用程序。知道如何处理它需要时间,并且不能保证学会它。还要记住,会有错误,没有办法解决:)

    查看这本 SOLID 电子书 - http://lostechies.com/wp-content/uploads/2011/03/pablos_solid_ebook.pdf,它会有所帮助。

    【讨论】:

    • 我明白这一点,但在某些时候需要处理细节。如果换了设备怎么办?然后呢?如果您需要更新一些设备参数怎么办?你是从头开始吗?如果您需要显示有关输入的信息怎么办?如果是文件还是设备?
    • “如果你需要显示输入信息怎么办?”。您将在界面中有一个 GetDisplayInformation() 方法。这样,每个输入都处理具体的操作方法。这不是唯一的方法,但它不会仍然存在于 IAudio 之类的东西中。
    • 设备改了怎么办+需要更新一些设备参数怎么办?在不知道细节的情况下,您似乎希望拥有一些与您拥有的每种输入类型直接关联的 UI 元素(因为您需要在 UI 中显示特定于设备的选项,但您也不希望所有 UI 代码与其余代码混合)。另一种选择是对设备 x 设备子类型进行一些映射,因为您可以拥有所有真正需要相同参数的相关设备的子集/在这种情况下,这些设备的接口也可能是有序的。
    • 如果需要更新一些设备参数怎么办?你是从头开始吗?由于您需要 UI x 类型,您可以让 UI 知道这些实例,因此 UI 中的更改会直接更新设备子类型特定的实例。另一种方法是通过一些中介,仍然允许有设备特定的更新事件。
    【解决方案2】:

    iInput 界面对我来说是正确的。我想对你所说的做出反应,这似乎是你唯一真正的问题:

    “也许我可以获取数据,但使用 InputFile 我需要指定文件名,而 InputSoundcard 将是其他设备特定信息”

    是的。但那是 method 特定的信息,还是 instance 特定的信息?对我来说,不带参数的 getData() 方法是完全可以接受的,每个实现都会使用实例属性中可用的任何参数。

    所以,是的,这是正确的做法,或者至少我是这么认为的 :)

    【讨论】:

    • 看来,如果您不尽其所能设计您的界面,您将来可能会遇到麻烦。如果文件名只需要更改怎么办?如果您只允许在构造函数中进行更改,那么您需要创建一个新对象,与仅更新字符串相比,它会影响性能。
    • 如果底层文件发生变化,输入实例中哪些可能的状态值得保留?
    • 这就是你在属性上使用 setter 和 getter 的原因。我以构造函数为例,但还有更多方法:c# 中的属性,java 中的 get/set 是常用模式,谁知道其他语言还有什么。重要的是这些参数不在 getData() 方法的职责范围内。