依赖倒置原则指定了一种解耦的方式,使得项目更加容易进行扩展。
依赖倒置原则遵循下面三个原则:高层模块不依赖底层模块的实现,两者都应该依赖于其实现。
抽象不依赖于细节。
细节依赖于抽象。
高层模块指的是调用端,底层模块指的是具体实现类。
什么是倒置?依赖正置是指依赖于实现细节,依赖倒置是指依赖其抽象。
下面以一个例子来具体说明依赖倒置的优点。
public class DependencyInversion {
public static void main(String[] args) {
new Driver().driver(new Benz());
}
}
class Benz {
public void run() {
System.out.println("奔驰可以运行");
}
}
class Driver {
public void driver(Benz benz) {
benz.run();
}
}
在上面的代码中我们以司机开车为例,假设司机有一辆奔驰车并且司机可以开这辆车。那么该司机若干年之后又买了一辆宝马车,我们这时候需要添加一个表示宝马车的类。
class BMW {
public void run() {
System.out.println("宝马可以运行");
}
}
但是司机类的driver方法只能开奔驰车,最直接的方法是在Driver类中添加可以开宝马的方法。
class Driver {
public void driverBenz(Benz benz) {
benz.run();
}
public void driverBMW(BMW bmw) {
bmw.run();
}
}
但是假设司机中了彩票,买了十几辆车,那么我们应该对每一辆车添加一个方法,这就倒置类与类之间的耦合度过大。
根据依赖倒置原则,抽象相对于细节来说更加稳定,因此我们需要在高层模块底层模块中依赖抽象,从而尽量避免底层模块的修改对高层模块的影响。
这里我们定义两个接口,分别表示汽车和飞机的抽象:
interface ICar {
public void run();
}
interface IDriver {
public void driver(ICar icar);
}
然后高层模块和底层模块分别依赖抽象:
class BMW implements ICar{
@Override
public void run() {
System.out.println("宝马可以运行");
}
}
class Benz implements ICar{
@Override
public void run() {
System.out.println("奔驰可以运行");
}
}
class Driver implements IDriver{
@Override
public void driver(ICar icar) {
icar.run();
}
}
当需求变化的时候,只需要创建ICar接口的实现类即可,从而保证了程序的扩展性。
倒置怎么理解 ? 依赖正置 ,我要开奔驰就依赖奔驰,面向实现编程,估计这也是90年代主要思想,后来这种方式有很大问题 所以要倒置即依赖抽象。
依赖传递的三种方式:
接口声明依赖,如上所述。
构造函数传递依赖:
public interface IDriver{
public void drive();
}
public class Driver implements IDriver{
private ICar car;
public Driver(ICar _car){
this.car = _car;
}
public void drive(){
this.car.run();
}
}
setter方法传递依赖:
public interface IDriver{
public void setCar(ICar car);
public void drive();
}
public class Driver implements IDriver{
private ICar car;
public void setCar(ICar car){
this.car = car;
}
public void drive(){
this.car.run();
}
}