[设计模式]之依赖倒转原则
摘要
首先提及下面向对象的四个好处
①可维护
②可扩展
③可复用
④灵活性好
可以把PC电脑理解成为一个大的软件系统,CPU、内存、硬盘、显卡等都可以理解为程序中封装好的类或者程序集,由于PC易插拔式,不管哪一个出问题,都可以在不影响别的部件的前提下进行修改或替换。
这种关系在面向对象中叫强内聚、松耦合。
在PC的世界里像CPU这种内聚力非常强的东东,只有AMD和Intel2大厂家,因为其核心的东西别人看不到,但它又独自成为产品,在电脑主板上插上就可以使用,这就是接口的最大好处,CPU只需要把接口定义好,而主板只需要预留与CPU针脚的插槽即可。
强内聚:像CPU一样,别的厂商木有办法制造,因为看不见其内部。
松耦合:像CPU的针脚与对应的主板插槽,坏了任何一个我们可以再换。
PC内存不够只要插槽足够就可以添加,硬盘不够我们可以使用移动硬盘,但是扩展是有限的,软件系统设计的好则可以无限扩展。
依赖倒转原则
依赖倒转原则:
A:高层模块不应该依赖底层模块。两个都应该依赖抽象。
B:抽象不依赖细节,细节应该依赖抽象。
模块间的依赖是通过抽象发生的,实现累之间不发生直接的关系,其依赖关系是通过接口或者抽象类发生的。
接口和抽象类不依赖于实现类,实现类依赖于接口或者抽像类
更加精简的定义就是“面向接口编程”--OOD的精髓之一。
在项目开发中为了使常用代码可以重复使用,我们一般会把这些代码写成许许多多函数的程序库,比如访问数据的代码一般会封装成模块,每次建新项目就去调用这些函数。
但是问题是,需要做新项目,发现业务逻辑的高层模块都是一样的,但客户用不同的数据库或存储信息方式,我们需要再次利用这些高层模块,但是高层模块与低层的访问数据库都绑定到一起了,没有办法复用这些高层模块,这就非常糟糕了。这就需要在设计时采用依赖倒转原则,不管是高层模块还是低层模块,都依赖于抽象,具体一点就是接口或抽象类,只要接口稳定那么任何一个更改都不用的担心其他受到影响,无论高层还是低层模块都可以很容易被复用,这才是最好的办法。
下面通过一个例子来体现依赖倒转原则可以减少类之间的耦合性,提高系统的稳定性,减少并行开发引起的危险,提高代码的可读性和维护性。
现在有车族越来越多,就通过张三开奔驰车来举例:首先我们可以通过2个类来描述2个对象如下图所示
奔驰车可以提供一个方法run代表车辆运行
public
class
Driver {
//司机的主要职责就是驾驶汽车
public
void
drive(Benz benz){
benz.run();
}
}
public
class
Benz {
//汽车肯定会跑
public
void
run(){
System.out.println(
"奔驰汽车开始运行..."
);
}
}
Client场景展现张三开奔驰车
public
class
Client {
public
static
void
main(String[] args) {
Driver zhangSan =
new
Driver();
Benz benz =
new
Benz();
//张三开奔驰车
zhangSan.drive(benz);
} }
所以依赖倒置原则闪亮登场,建立2个接口IDriver和ICar分别定义汽车和司机的各个职责,如下图所示
public
interface
IDriver {
//是司机就应该会驾驶汽车
public
void
drive(ICar car);
}
public
interface
ICar {
//是汽车就应该能跑
public
void
run();
}
public
class
Benz:
ICar{
//汽车肯定会跑
public
void
run(){
System.out.println(
"奔驰汽车开始运行..."
);
}
}
public
class
BMW :
ICar{
//宝马车当然也可以开动了
public
void
run(){
System.out.println(
"宝马汽车开始运行..."
);
}
public
class
Client {
public
static
void
main(String[] args) {
IDriver zhangSan =
new
Driver();
ICar bmw =
new
BMW();
//张三开奔驰车
zhangSan.drive(bmw);
}
}
项目中实践几条规则:
1.每个类尽量有接口或者抽象类,或者抽象类和接口都具备。
——这是依赖倒置的基本要求,接口和抽象类都是抽象,有了抽象才能依赖倒置。
2.变量的显示类型尽量是接口或者抽象类。
3.任何类都不应从具体类派生。
——在项目初期写架子的时候适用此规则,这不是绝对的,很多项目维护扩展功能时可以不考虑去继承最高类。
4.尽量不要覆写基类的方法
——如果基类是抽象类,而且这个方法已经实现了,子类尽量不要覆写,类间依赖是抽象的,覆写了抽象方法会对性能产生一定影响。
5.结合里氏替换原则
里氏代换原则:子类型必须能够替换掉它们的父类型。
意思是说只有当子类可以替换掉父类,软件单位的功能不受影响,父类才能被真正复用,而子类也能够在父类的基础上扩展新的行为。
我们可以得出一个通俗的规则:接口负责写public属性和方法,并且声明和其他对象的依赖关系,抽象类负责公共累构造的实现,实现类准确实现业务逻辑,同时适当的对父类进行细化。
为什么叫依赖倒置:人们正常的思维要实现开奔驰车就得依赖奔驰车,要想使用笔记本就必须依赖笔记本,然而编程是对现实事物的抽象,抽象的结果就产生了接口和抽象类,进而产生了抽象间的依赖,代替了人们传统思维间事物的依赖,所以“倒置”就产生了。