【六大设计原则】3. 依赖倒置原则 -Dependence Inversion Principle:

前端之家收集整理的这篇文章主要介绍了【六大设计原则】3. 依赖倒置原则 -Dependence Inversion Principle:前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

DIP,Dependence Inversion Principle:@H_502_7@

High level modules should not depend upon low level modules. Both should depend upon abstractions.
@H_502_7@

Abstractions should not depend upon details. Details should depend upon abstractions.
@H_502_7@


@H_502_7@

“面向接口编程”@H_502_7@

  • 高层模块不应该依赖低层模块,两者都应该依赖其抽象;——模块间的依赖通过抽象发生。实现类之间不发生直接的依赖关系(eg. 类B被用作类A的方法中的参数),其依赖关系是通过接口或抽象类产生的;
  • 抽象不应该依赖细节;——接口或抽象类不依赖于实现类;
  • 细节应该依赖抽象;——实现类依赖接口或抽象类。

何为“倒置”?@H_502_7@

依赖正置:类间的依赖是实实在在的实现类间的依赖,即面向实现编程,这是正常人的思维方式;@H_502_7@

而依赖倒置是对现实世界进行抽象,产生了抽象间的依赖,代替了人们传统思维中的事物间的依赖。
@H_502_7@


@H_502_7@

依赖倒置可以减少类间的耦合性、降低并行开发引起的风险。@H_502_7@


@H_502_7@

示例(减少类间的耦合性):@H_502_7@

例如有一个Driver,可以驾驶Benz:@H_502_7@

public class Driver{
    public void drive(Benz benz){
        benz.run();
    }
}
public class Benz{
    public void run(){
        System.out.println("Benz开动...");
    }
}

问题来了:现在有变更,Driver不仅要驾驶Benz,还需要驾驶BMW,怎么办?

Driver和Benz是紧耦合的,导致可维护性大大降低、稳定性大大降低(增加一个车就需要修改Driver,Driver是不稳定的)。@H_502_7@


@H_502_7@

示例(降低并行开发风险性):
@H_502_7@

如上例,Benz类没开发完成前,Driver是不能编译的!不能并行开发!@H_502_7@


@H_502_7@

问题由来:
@H_502_7@

类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。@H_502_7@

解决办法:@H_502_7@

将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。@H_502_7@


@H_502_7@

上例中,新增一个抽象ICar接口,ICar不依赖于BMW和Benz两个实现类(抽象不依赖于细节)。@H_502_7@

1)Driver和ICar实现类松耦合@H_502_7@

2)接口定下来,Driver和BMW就可独立开发了,并可独立地进行单元测试
@H_502_7@


@H_502_7@

依赖有三种写法:@H_502_7@

1)构造函数传递依赖对象(构造函数注入)@H_502_7@

@H_502_7@

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();
    }
}

2)setter方法传递依赖对象(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();
    }
}

3)接口声明依赖对象(接口注入)@H_502_7@


@H_502_7@

建议:
@H_502_7@

DIP的核心是面向接口编程;DIP的本质是通过抽象(接口、抽象类)使各个类或模块的实现彼此独立,不互相影响。@H_502_7@

在项目中遵循以下原则:@H_502_7@

  1. 每个类尽量都有接口或抽象类
  2. 变量的表面类型尽量使接口或抽象类
  3. 任何类都不应该从具体类派生*——否则就会依赖具体类。
  4. 尽量不要重写父类中已实现的方法——否则父类就不是一个真正适合被继承的抽象。
  5. 结合里氏替代原则使用

猜你在找的设计模式相关文章