当(当前)只是一个实现它的类时,你应该创建一个接口吗?

如果可能有其他东西可以使用它,或者等到实际需要它然后重构使用接口,你是否应该总是创建一个接口?

对界面进行编程通常看起来像是一个合理的建议,但那时就有YAGNI ……

我想也许这取决于具体情况。 现在我有一个对象代表一个可以包含食谱或其他文件夹的文件夹。 而不是直接使用Folder,我应该担心像IContainer这样的实现吗? 在未来的情况下,我希望有一个参考其他子食谱的配方(比如一个苹果馅饼配方,也是馅饼皮配方的容器)

它总是取决于具体情况。 如果你知道将有另一个使用该接口的类,那么是的,创建接口类以便以后节省时间。 但是,如果你不确定(大多数时候你不是),那么等到你需要它。

现在,这并不意味着忽略界面的可能性 – 考虑对象的公共方法,以及稍后制作界面,但不要将你的代码库与你实际上不需要的任何东西混为一谈。

总会有一个测试使用它,对(你做unit testing,不是吗?)。 这意味着它总是使用它的N + 1个类,其中N是在应用程序中使用您的类的类的数量。

除了dependency injection之外,接口的另一个目的是分离关注点,以便您的类实际上可以实现多个接口。

记住所有这些,但如果没有在开头实现,你可以随后通过重构引入接口。

我想说这更多地取决于你将使用该类的地方数量,而更少取决于有多少类可能实现该接口。 如果你只在一两个地方使用Folder,那么我会说等到实际需要接口之后才实现它并重构。 但是,如果要在100个不同的地方使用Folder,那么您可以通过预先编程到接口来节省一些时间。

一般情况下,如果只有一个类要实现它,你就不应该费心去创建一个接口,即使你预期可能有一个类,因为可能存在实现问题,直到该类实际测试到场景,在这种情况下,过早创建的界面可能有太多的memebrs或可能缺少一个成员。

例如,.NET Framework Ba​​s Class Library团队承认在包含SyncRoot属性时过早地设计了ICollection 。 对于后来的通用ICollection他们决定将其删除( http://blogs.msdn.com/bclteam/archive/2005/03/15/396399.aspx )。

如果您要创建一个实现相同接口的模拟对象,那么这将被视为第二个实现,它certificate了创建接口的合理性。 但是,并非所有的unit testing都需要模拟风格的界面。

将接口视为定义语义或概念的契约。 这是一种通用的方法,而不是真正的语言。 在OO的上下文中,如果您正在使用单个inheritance模型,那么有一个很好的例子可以优先选择接口而不是类来定义对象模型,因为单个超类路径非常珍贵并且您希望将其保存为比定义在对象或方法上公开的属性更“实质”的东西。

拥有IContainer语义(契约)是一个相当糟糕的理由从你的文件夹中创建一个接口; 最好让你的文件夹(如果它正在做任何非平凡的逻辑)在你的语言的核心框架中“实现”(可能已经存在的)IContainer或ICollection接口。

与往常一样,更好的选择完全取决于具体问题。 如果您的食谱也是文件夹(?!),您可能正在考虑父子或组合关系 – 如果您的系统中有其他元素,则可以(并且应该)使用接口表达的语义“操作”使用那种语义组成的东西。

接口有一些开销(编程方面),如果你发现自己只需要一组Woof和IWoof类和接口,那么你就会知道你可能不需要表达你在接口方面的问题 – 简单的类就足够了。

作为一个规则,对于任何我,你应该至少有几个具体的类(除了IImpl之外还有更有意义的名字,或者)。

希望有所帮助。

很多人已经提出了非常合理的建议。 我想补充的一件事是,如果您希望避免直接硬依赖于具体类,那么接口将通过提供松散耦合来提供帮助。 如果您正在创建基于插件的架构,那么接口绝对是您的选择。 此外,如果您计划并排或稍后编写unit testing,您可能会注意到调用文件夹类的代码必须带有一个具体的实现,以使调用代码可以测试。 如果您对文件夹类的具体实现又与数据库或服务进行通信,那么您将需要将其延续到您的测试中,这将很快变得难以处理。 只需2美分。