对接口而不是对实现进行编码的目的是避免泄漏实现细节,否则这些细节将限制您的程序。
考虑原始代码版本使用a HashMap
并将其公开的情况。
private HashMap foo = new HashMap();
public HashMap getFoo() { return foo; } // This is bad, don't do this.
这意味着对的任何更改getFoo()
都是对API的重大更改,并且会使使用它的人们不满意。如果您要保证的foo
只是一张地图,则应返回该地图。
private Map foo = new HashMap();
public Map getFoo() { return foo; }
这使您可以灵活地更改代码内部的工作方式。您意识到foo
实际上需要成为一个按特定顺序返回事物的Map。
private NavigableMap foo = new TreeMap();
public Map getFoo() { return foo; }
private void doBar() { ... foo.lastEntry(); ... }
对于其余的代码,这没有任何破坏。
您以后可以在不破坏任何条件的情况下加强班级给予的合同。
private NavigableMap foo = new TreeMap();
public NavigableMap getFoo() { return foo; }
private void doBar() { ... foo.lastEntry(); ... }
这深入研究了Liskov替代原理
可替换性是面向对象编程中的一个原则。它指出,在计算机程序中,如果S是T的子类型,则可以用类型S的对象替换类型T的对象(即,类型S的对象可以替换类型T的对象),而无需更改任何期望的对象该程序的属性(正确性,执行的任务等)。
由于NavigableMap是Map的子类型,因此可以在不更改程序的情况下进行此替换。
公开实现类型使您难以在需要进行更改时更改程序的内部工作方式。这是一个痛苦的过程,并且很多时候会创建丑陋的解决方法,这只会在以后给编码器带来更多的痛苦(我正在看您以前的编码器,由于某些原因,该编码器一直在LinkedHashMap和TreeMap之间改组数据–每当我信任我看到svn怪你的名字,我担心)。
您仍然希望避免泄漏实现类型。例如,由于某些性能特征,您可能希望实现ConcurrentSkipListMap而不是实现,或者只是喜欢java.util.concurrent.ConcurrentSkipListMap
而不是java.util.TreeMap
在import语句中实现。