我读到了关于Spring如何鼓励你在代码中使用接口的地方.我没有看到它.spring xml配置中没有接口的概念.Spring的哪一部分实际上鼓励您使用接口(除了文档)?
该依赖倒置原则解释了这一点.特别是图4.
A.高级模块不应该依赖于低级模块.两者都应该依赖于抽象.
B.抽象不应该依赖于细节.细节应取决于抽象.
将上面链接中的示例翻译成java:
public class Copy { private Keyboard keyboard = new Keyboard(); // concrete dependency private Printer printer = new Printer(); // concrete dependency public void copy() { for (int c = keyboard.read(); c != KeyBoard.EOF) { printer.print(c); } } }
现在有依赖倒置:
public class Copy { private Reader reader; // any dependency satisfying the reader interface will work private Writer writer; // any dependency satisfying the writer interface will work public void copy() { for (int c = reader.read(); c != Reader.EOF) { writer.write(c); } } public Copy(Reader reader, Writer writer) { this.reader = reader; this.writer = writer; } }
现在Copy
支持的不仅仅是从键盘复制到打印机.
它能够从任何地方复制Reader
到任何地方Writer
而无需对其代码进行任何修改.
现在有了Spring:
也许:
为类定义接口时,它有助于依赖注入.您的Spring配置文件中没有关于接口的任何内容 - 您只需输入类的名称即可.
但是如果你想注入另一个提供"等效"功能的类,那么使用界面确实有帮助.
例如,说你有一个分析网站内容的课程,你用Spring注入它.如果您注入的类知道实际的类是什么,那么为了更改它,您将不得不更改大量代码以使用不同的具体类.但是如果你创建了一个Analyzer
界面,你就可以轻松地注入你的原始内容,DefaultAnalyzer
就像你嘲笑一样,DummyAnalyzer
或者甚至是另一个基本相同的东西,比如一个PageByPageAnalyzer
或其他东西.为了使用其中一个,你只需要更改你在Spring配置文件中注入的类名,而不是通过你的代码更改类.
在我真正开始看到它的用处之前,它花了我一个半个项目.像大多数事物(在企业语言中)最终都是有用的,一开始似乎是毫无意义的工作,直到你的项目开始增长,然后你通过做更多的工作预先发现你节省了多少时间.
这里的大部分答案都是某种形式的"你可以轻松换掉实现",但我认为他们没有回答的是为什么?部分.对此我认为答案几乎是可测试的.无论您是否使用Spring或任何其他IOC框架,使用依赖注入都可以使您的代码更容易测试.如果是编写器而不是PrinterWriter,您可以在单元测试中模拟Writer接口,并确保您的代码以您期望的方式调用它.如果您直接依赖于类实现,您唯一的选择是走到打印机并检查它,这不是非常自动化.此外,如果您依赖于调用类的结果,无法模拟它可能会阻止您在测试中访问所有代码路径,从而降低其质量(可能)简而言之,您应该将对象图创建与应用逻辑分离.这样做可以使您的代码更容易测试.
还没有人提到在很多情况下并不需要创建一个接口以便可以快速切换实现类,因为只需要一个实现类即可。
当不需要创建接口时,将成对创建类(接口加实现),添加不必要的样板接口并造成潜在的依赖混乱,因为在XML配置文件上,组件有时会由其接口引用,有时会由其实现引用,在运行时没有任何后果,但是在代码约定方面不连贯。