相比于继承,OO中多态的概念要更重要。一个接口可以对应多个实现类,对于声明为接口类型的方法参数、类的字段,它们要比实现类更易于扩展、稳定,这也是多态的优点。假如我以实现类作为方法参数定义了一个方法void doSomething(ArrayList list),但如果领导哪天觉得 ArrayList不如LinkedList更好用,我将不得不将方法重构为void doSomething(LinkedList list),相应地要在所有调用此方法的地方修改参数类型(很遗憾地,我连对象创建也是采用ArrayList list = new ArrayList()方式,这将大大增加我的修改工作量)。如果领导又觉得用list存储数据不如set好的话,我将再一次重构方法,但这一次我变聪明了,我将方法定义为void doSomething(Set set),创建对象的方式改为Set set = new HashSet()。但这样仍不够,如果领导又要求将set改回list怎么办?所以我应该将方法重构为void doSomething(Collection collection), Collection的抽象程度最高,更易于替换具体的实现类。即便需要List或者Set固有的特性,我也可以做向下类型转换解决问题,尽管这样做并不安全。
面向接口编程最重要的价值在于隐藏实现,将抽象的实现细节封装起来而不对外开放,封装这对于Java EE 中的分层设计和框架设计尤其重要。但即便在编程时使用了接口,我们也需要将接口和实现对应起来,这就引出如何创建对象的问题。在创建型设计模式中,单例、工厂方法(模板方法)、抽象工厂等模式都是很好的解决办法。现在流行的控制反转(也叫依赖注入)模式是以声明的方式将抽象与实现连接起来,这既减少了单调的工厂类也更易于单元测试。