关于Java:对接口进行编码?

Coding to interfaces?

本问题已经有最佳答案,请猛点这里访问。

我想巩固我对"编码到接口"概念的理解。据我所知,我们创建接口来描述预期的功能,然后在具体的类中实现这些"契约"。要使用接口,只需在具体类的实例上调用方法。

明显的好处是了解具体类所提供的功能,而不管它的具体实现是什么。

基于以上内容:

  • 在我对"接口编码"的理解中,有什么谬误吗?
  • 我错过的接口编码有什么好处吗?
  • 谢谢。


    只有一个可能的修正:

    To use the interface one can simply call the methods on an instance of the concrete class.

    我们可以在类型接口的引用上调用方法,而类型接口恰好使用具体的类作为实现:

    1
    2
    3
    List<String> l = new ArrayList<String>();
    l.add("foo");
    l.add("bar");

    如果您决定切换到另一个列表实现,那么客户机代码将不做任何更改:

    1
    List<String> l = new LinkedList<String>();

    这对于隐藏实现细节、自动生成代理等特别有用。

    您会发现像Spring和Guice这样的框架鼓励对接口进行编程。它是面向方面编程、事务管理的自动生成代理等思想的基础。


    你的理解似乎是正确的。你的同事刚在你的办公桌旁晃来晃去,把你醉酒的老板主演的圣诞晚会的所有最新照片都装到他的拇指上。你的同事和你不会再想这个拇指驱动器是如何工作的,对你来说它是一个黑匣子,但是你知道它是如何工作的,因为它有USB接口。

    不管是沙盘还是钛合金(甚至不确定是品牌),大小/颜色也不重要。事实上,唯一重要的是它没有损坏(可读),而且它可以插入USB。

    您的USB拇指驱动器遵守合同,它本质上是一个接口。我们可以假定它履行了一些非常基本的职责:

  • 插入USB
  • 遵守合同方法copydatato:

    公共接口IUSB{void copydatato(string somepath);//用于将数据从缩略图驱动器复制到…}

  • 遵守合同方法复制数据来源:

    公共接口IUSB{void copy data from();//用于将数据从PC复制到缩略图驱动器}

  • 好吧,也许不是这些方法,但是IUSB接口只是缩略图驱动器供应商必须遵守的一个契约,以确保不同平台/供应商之间的功能。因此Sandisk通过接口进行了拇指驱动:

    1
    2
    3
    4
    public class SanDiskUSB : IUSB
     {
      //todo: define methods of the interface here
     }

    Ari,我认为你已经对接口的工作方式有了一个很好的理解(从它听起来是什么样子)。


    To use the interface one can simply call the methods on an instance of the concrete class.

    通常,您将有一个类型化为接口类型的变量,因此只允许访问接口中定义的方法。

    The obvious benefit is knowing of the functionality provided by the concrete class, irrespective of its specific implementation.

    某种程度上。最重要的是,它允许您编写采用接口类型参数的API。然后,API的用户可以在自己的类中传递(实现这些接口),而代码将在这些类上工作,即使它们在编写时不存在(例如Java.UTI.SARS.SORT(),它能够对实现EDCOX1×0的任何东西排序,或者附带一个合适的EDCOX1(1))。

    从设计的角度来看,接口允许/强制在API契约和实现细节之间进行明确的分离。


    主要的优点是,使用接口可以将类与其依赖项松散地耦合在一起。然后,您可以更改一个类,或者实现一个新的具体接口实现,而不必更改依赖它的类。


    针对接口进行编码的目的是将代码与正在使用的具体实现分离。也就是说,您的代码不会对具体类型进行假设,只会对接口进行假设。因此,可以在不需要调整代码的情况下交换具体的实现。


    您没有列出有关如何获得接口实现的部分,这很重要。如果使用构造函数显式地实例化实现类,那么您的代码将绑定到该实现。您可以使用一个工厂为您获取一个实例,但是之后您就可以像以前那样与工厂绑定到实现类了。第三种选择是使用依赖注入,即让工厂将实现对象插入使用它的对象,在这种情况下,您可以避免让使用对象的类绑定到实现类或工厂。


    As I understand it, one creates interfaces to delineate expected functionality, and then implements these"contracts" in concrete classes.

    我在你的想法中看到的唯一的一种变异是——你会说出预期的契约,而不是预期的功能。功能在具体的类中实现。接口只声明您将能够调用实现具有预期方法签名的接口的东西。功能对调用对象隐藏。

    这将允许您将您的思想扩展到多态性,如下所示。

    1
    2
    3
    4
    5
    SoundMaker sm = new Duck();<br/>
    SoundMaker sm1 = new ThunderousCloud();

    sm.makeSound(); // quack, calls all sorts of stuff like larynx, etc.<br/>
    sm1.makeSound(); // BOOM!, completely different operations here...


    我认为您可能已经暗示过这一点,但我相信对接口进行编码的最大好处之一是您正在打破对具体实现的依赖。您可以实现松耦合,并使在不更改太多代码的情况下切换特定实现更容易。如果您只是在学习,我将了解各种设计模式,以及它们如何通过编码到接口来解决问题。先读书头:设计模式真的帮了我点东西。