我编写的每个类都应该坚持一个接口吗?


10

我正在用Typescript编写游戏,并决定继续尝试坚持“ 基于接口的编程 ” 的思想,在该思想中,您基于对象的接口而不是实现来编写代码。

我写了很多接口和实现它们的类,然后退后一步,意识到这些类足够简单,以至于我可能永远不需要更改实现,因为实际上只有一种方法可以完成班级确实做到了(Phaser.Sprite以受限方式移动坦克就像坦克一样)。

然后,我记得几年前读过有关YAGNI的想法,这基本上是您不应过度设计代码以包含您可能永远不会使用的东西。

遵循最佳实践,每个类都应该实现一个接口,还是应该将其限制为您希望将来可能替换掉的类?


请记住,当您使用实际的类作为参数时,您也正在为该类的接口编码。没有人强迫您使用该特定类,您可以很好地继承它并提供全新的功能,但这似乎并不正确。存在使人们更容易将想法束之高阁的界面。可悲的是,不,您实际上并不需要所有的接口。
安迪

Answers:


6

具有接口的原因是因为它简化了多态性。意味着您可以按合同发送实例,而不用知道实例的实际实现。例如,您可以将“ Reader”发送给方法,以便这种被调用的方法可以使用其“ read()”方法。通过声明一个接口“ Reader”,您可以通过实现它指定的方法来使任何对象都符合该协定。这样,即使合同基础的对象可能完全不同,任何调用方都可以假定某些方法将存在。

这样可以将多态与基类脱钩,并且通过暗示一个契约,也可以在类链边界之间实现。

现在...仅当您需要多个继承链以相同的方式运行,或者您将有许多具有常见行为的基类想要传递给其他用户时,这才有用。

如果您只有一个继承链(基类->子类)或仅基类,或者您不需要实际将相关对象传递给其他人或以一般方式使用它们,则无需添加接口实现,因为这样无用。


我还要补充一点,接口应该对抽象进行建模,所以不要仅仅通过提升类的所有公共成员来创建它们。考虑一下该类表示什么,然后仅将这些内容放入该类型的任何对象应具有的接口中。您可能还会为单个类创建多个接口(例如MovesShoots对于您的坦克示例)。
TMN

7

如果不确定是否确实需要这些接口,则可能不需要。这是YAGNI原则的核心。您需要能够交换实现时,可以引入一个接口。


6

为每个类创建一个接口有点过大。从纯粹的面向对象的角度来看,每个类都已经有一个interface。接口不过是类的面向公众的方法和数据成员。

我们通常使用“接口”来表示“使用interface关键字定义的Java类”或“仅具有公共纯虚拟函数的C ++类”。这些是有用的抽象,因为它们使类的接口与其实现分离。

考虑到这一点,请在适当的时候使用接口。

  • 一个接口会有多个实现吗?如果是这样,则可能是将常见的,面向公众的方法提取到界面中的一种可能。

  • 我是否会将潜在接口的实现传递给其他不应该知道模块内部工作原理的模块?接口在这里很有用,因为它减小了模块之间接触点的大小。

注意上面的狡猾的词:“可能”是候选者,“可能”是有用的。对于给定的情况,没有硬性规定可以说“是”或“否”。

话虽这么说,拥有所有功能的接口最有可能被杀。如果您看到此模式,那么您将走得很远:

interface I {
  int getA()
  int getB()
  ...
  int getY()
  int getZ()
}

class C : I {
  int getA() { ... }
  int getB() { ... }
  ...
  int getY() { ... }
  int getZ() { ... }
}

使用接口的另一个原因是测试系统是否需要它,这可能取决于您的语言和测试框架。希望你不会需要做到这一点,当然。
达里安

@Darien:测试系统可能需要接口的原因是因为测试实际上使用了不同的(模拟的)实现,使您回到适合使用接口的第一句话。
Bart van Ingen Schenau,2016年

一些很棒的东西。只需考虑一下:接口只不过是面向公众的方法和类的数据成员。尽管这对于接口实现是正确的,但对于从未实现但仍未实现的接口肯定不成立,尽管这是被允许的-这将有点代码味道。
罗比·迪

@RobbieDee对于例如Java interface来说确实如此,恰好发生在Java中的所有内容interface也是其面向公众的接口(OO概念)。

大家!写下答案的第二和第三句。层压它。把它放在你的钱包里。经常参考。
–radbobo

5

对于新开发人员而言,将接口视为一种不便之处(您只是因为被告知这是“最佳实践”而已而添加)是非常诱人的。如果你盲目地做这个,也有点的货物崇拜编程

有很多很好的理由,您应该考虑将接口用于更大的开发,而不是将一组类放在一起。

模拟框架

如果您想测试多层应用程序而不必为各个层构建对象,那么无疑将要使用模拟框架来模拟这些层。接口在这里被广泛使用。

依赖注入

尽管由于它们的过大膨胀而使它们有些失宠,但这个想法很合理-能够基于接口简单地交换混凝土。在许多设计模式(例如工厂模式)中也可以找到该原理。


这些方法归纳为dSOLID原则。这样做的麻烦是-使用抽象而不是凝结。

就像设计模式本身一样,何时使用它们是一种判断。要点是要了解接口的用途,而不仅仅是因为觉得必须将它们粘在类上。有DIP和YAGNI的种种好处商量好了这里


请注意,依赖注入和IoC容器是完全不同的两件事(一是设计原则,另一是通过使用各种框架将该原则具体付诸实践的一种方式)。您可以不使用IoC容器而使用DI。
2016年

@kai “您可以在不使用IoC容器的情况下使用DI”。我认为,更多成熟的开发商店可以(也可以这样做)。表面上看这是一个简单的概念,根本不需要污染代码。乔尔也有类似的看法。
罗比·迪

YAGNI非常棘手。无论是什么哲学,在大多数情况下,实际上,YAGNI都是偷工减料的借口。避免联轴器应更加重视。在许多Scrum会议上看到一个开发人员自称是因为其他人未完成工作而被阻止,这令人沮丧。如何阻止另一个开发人员可以节省任何时间?我的建议是使用接口避免耦合。当然,不必为Model类使用接口。
Ripal Barot
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.