当前位置: 首页 > 编程学习 > 软件工程 > 面向对象 > 正文

深入了解面向对象设计原则“依赖倒转原则”

2018-04-22 来源:博客园/醒者呆

一千个人眼里有一千个哈姆雷特,下面我尝试用深入浅出的语言贯穿到“控制反转”,“依赖注入”,“面向抽象编程”,以及“面向接口编程”这几个概念。

传递参数,关联(组合&聚合)关系时,要尽量引用高层次的抽象类,使用基类和接口进行变量类型的声明,参数类型的声明,数据类型转换(也是向高层次的抽象类转),而不要用具体的子类。

以上总结为“控制反转”,也叫“面向抽象编程”。

真到了要使用具体子类的时候,采用“依赖注入”的方式:

构造注入,通过构造函数传入具体类的对象

setter注入,通过setter方法传入具体类的对象

接口注入,通过在接口中声明的业务方法,来传入具体类的对象作为方法的参数

——> 引申到“面向接口编程”的概念,接口的意思就是“如果你是***的话,你能干嘛?”,接口中定义的是能干嘛,具体怎么干不告诉你,等你是了(即实现该接口)自己去想具体怎么干。

接口是抽象概念的一种,当你在面向抽象编程时,传递参数,关联关系,使用的是接口来声明变量类型,参数类型以及数据类型转换,而不是具体的类,这就是面向接口编程。

所以,总结出这些概念的关系是,面向对象编程的中心思想是面向抽象编程,而面向接口编程是面向抽象编程的一种。

那么问题又来了,如果面向接口编程只是面向抽象的一种,那么另一种是什么呢?

另一种就是抽象基类,要注意区分这里的基类的概念,它包含abstract关键字的class,也包含普通父类(普通父类也是其众多子类的抽象化身),这里主要多说一下abstract class,它很容易与接口混淆,那么abstract class与接口的区别是什么?

abstract class可以包含有方法体的非抽象方法,可以包含任意作用域的成员数据。而接口一般不使用成员数据(即使有也是自动转为public static final类型),接口的所有方法都是没有方法体的抽象方法(接口内部不用abstract关键字)。

abstract class是对属性,行为的抽象,同时也可以有自己的具体方法。而接口只是对行为的抽象,接口更像是abstract class的特殊情况。

这两种不同的抽象概念更好的支持了Java多态(一个基类可以有很多子类is-a,一个类可以实现很多接口like-a)。abstract class仍然是个类,必须是相同种族抽象出来的类,例如动物类,熊猫类,而接口只是对行为的抽象,不管谁实现他,也不管他们是否是一个种族,例如动物和汽车都可以跑,那他们都可以实现具有“跑”行为的接口,对于接口本身来讲,他并不关心你是动物还是汽车,他只管定义他的“跑”就行了。

依赖倒转原则,总结一句话就是定义时用抽象类型(基类或者接口),运行时注入具体类型。

开闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段。