依赖倒置原则
定义:高层模块不应该依赖底层模块,二者都应该依赖其抽象: 抽象不应该依赖细节;细节应该依赖抽象。
问题由来:类A直接依赖类B,假如要将类A改成依赖类C,则必须通过修改类A的代码来到达。这种情景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作,假如修改类A,会给程序带来没有必要的风险。
解决方案:将类A修改为依赖接口o,类B和类C各自实现接口o,类A通过接口O与类B或者类C发生联系,则会大大降低修改类A的几率。
依赖倒置原则基于这样的一个事实:相对于细节的多样性,抽象的东西要稳定的多,以抽象为基础搭建起来的架构比以细节搭建起来的架构要稳定的多。再java中,抽象指的是抽象类或接口,细节则是具体实现的类,使用抽象类或接口是想制定规定好的契约和规范,而不去干涉任何具体的操作,把展现细节的任务给他们的实现类去完成。
依赖倒置的原则的核心思想是面向接口编程,我们依旧用一个例子来说面向接口编程比面向实现编程好,并且体现好在哪里?
代码如下:
package test1;
public classOpposite_Rely {
publicstaticvoidmain(String[] args) {
XiaoMin xiaom=new XiaoMin();
xiaom.playWho(new FootBall());
}
}
class FootBall{
public String playWhat()
{
return "他踢足球";
}
}
class XiaoMin{
public void playWho(FootBall ball){
System.out.println("小明想踢球呢!!");
System.out.println(ball.playWhat());
}
}
运行结果:
小明想踢球呢!!
他踢足球
运行结果出来,假如有一天小明,想玩篮球的时候。
代码
class BasketBall{
publicString playWhat(){
return "小明玩篮球";
}
小明同志却办不到了,因为他不会了,这太荒谬了吧,只是将足球换成篮球了,居然必须修改XiaoMin类才能玩球,加入以后再换成排球? 羽毛球呢? 还要不断修改xiaomin类,这显然不是最好的设计.原因就是xiaomin类和FootBall类耦合性太高了,必须降低他们的耦合度才行.
我们因此引入一个抽象的接口Ball,球.
代码如下:
package test2;
public classOpposite_Rely {
public staticvoidmain(String[] args) {
XiaoMinxiaom=newXiaoMin();
xiaom.play(new FootBall());
xiaom.play(new BasketBall());
}
}
class XiaoMin{
public void play(Ball ball)
{
System.out.println("小明想踢球呢");
System.out.println(ball.playWhat());
}
}
interface Ball
{
publicString playWhat();
}
class BasketBallimplementsBall{
publicString playWhat(){
return "小明玩篮球!";
}
}
class FootBall implements Ball{
public String playWhat(){
return "小明玩足球!";
}
}
运行结果
小明想踢球呢
小明玩足球!
小明想踢球呢
小明玩篮球!
修改之后,无论以后怎么扩展Opposite_rely类,都不需要修改xiaoMin类了,这只是一个简单的例子。实际情况中,代表高层模块的xiaomin类将负责主要的业务逻辑,一旦需要对它进行修改,引入错误的风险极大。所以遵守依赖倒置则可以降低类与类之间的耦合性,提高系统的稳定性,降低修改程序造成的风险。
采用依赖倒置原则给多人并发开发带来了极大地便利,比如上面的例子中。原来xioamin类和ball类直接耦合时,xiaomin类必须等ball类编码完成后才能进行编码,因为mother类依赖于ball类。修改后的程序则可以同时打工,互不影响。因为xiaomin类和ball类一点关系也没有。参与协作开发人员越多,项目越大时,采用依赖倒置原则的意义越重大。现在流行的TDD开发模式就是依赖倒置原则,使最成功的应用..
传递依赖关系有三种方式,以上的例子中使用的方式是接口传递,另外还有两种传递方式,构造方法传递和setter方法传递。
在实际编程中,我们一般需要做到如下三点
1底层模块尽量都要有抽象类或接口,或两者都有。
2变量的声明类型尽量是抽象类或接口。
3使用继承时使用替换原则
依赖倒置原则的核心是我们面向接口编程,理解面向接口编程,也就理解了倒置依赖了.