原 设计模式之禅——六大原则(依赖倒置原则)

依赖倒置原则定义:

高层模块不应该依赖底层模块,两者都应该依赖其抽象;
抽象不应该依赖细节;
细节应该依赖抽象

  • 每一个逻辑的实现都是逻辑的实现都是由原子逻辑组成的,不可分割的原则逻辑就是底层模块,原则逻辑的再组装就是高层模块。
  • 在Java中,抽象就是接口或抽象类,两者都是不能直接被实例化的在Java中,抽象就是接口或抽象类,两者都是不能直接被实例化的
  • 细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点就是直接被实例化,也就是new xx()。细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点就是直接被实例化,也就是new xx()。

依赖倒置原则在Java语言中的变现:

  • L 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。
  • 接口或抽象类不依赖于实现类
  • 实现类依赖接口或抽象类

更加精简的定义就是“面向接口编程”—-OOD(Object-Oriented Design,面向对象设计)的精髓之一。
没有实现依赖倒置原则的司机开车的实例:

public class Driver{
    public void drive(Benz benz){
        benz.run();
    }
}
----------
public class Benz{
    public void run(){
        System.out.println("奔驰开始跑了");
    }
}


----------
public class client{
    public static void main(String[] args){
        Driver tom = new Driver;
        Benz benz = new Benz();
        tom.drive(benz);]
    }
}

如果这里tom要去开宝马的车,就需要去修改代码。原因是司机和奔驰是紧耦合的关系(司机类依赖于Benz的具体实现类),结果导致系统的可维护性降低。

依赖倒置原则还可以减少并行开发的风险,什么是并行开发的风险?并行的最大风险就是风险扩散,本来只是一个程序的错误,逐步波及一个功能,模块,甚至整个项目。

现在根据依赖倒置原则重新设计代码:

public interface IDriver{
    public void drive(Icar car);
}
----------
public class Driver implements IDriver{
    public void drive(Icar car){
        car.run();
    }
}
----------
public interface ICar{
    public void run();
}
----------
public class Benz implements Icar{
    public void run(){
        System.out.println("奔驰开跑");
    }
}
----------
public class BWM implements Icar{
    public void run()
        System.out.println("宝马开跑");
    }
}
----------
public class Client{
    public static void main(String[] args){
        IDriver tom = new Driver();
        Icar bwm = new BWM();
        tom.drive(bwm);
    }
}
--------------------- 

开发过程中,A开发司机类,B开发汽车类,二者进度万一有偏差怎么办?A如果比B快很多难道也要一直等着B吗?其实,我们只需要制定出二者的接口就可以独立的运行,而且项目之间的单元测试也可以独立的运行,而TDD(Test-Driven Development,测试驱动开发)并发模式就是依赖倒置原则的最高级应用。

public interface IDriver{
    public void drive(Icar car);
}
----------
public interface ICar{
    public void run();
}
----------
package com.sdkd.hms12;

import org.jmock.Mockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.Test;

import junit.framework.TestCase;

public class DriverTest extends TestCase{
    Mockery context = new JUnit4Mockery();
    @Test
    public void testDriver(){
        final ICar car = context.mock(ICar.class);
        IDriver driver = new Driver();
        context.checking(new Expectations(){
            {
                oneOf(car).run();
            }
        });
        driver.drive(car);
    }
}

依赖的三种写法:
1、构造函数传递依赖对象
2、Setter依赖注入
3、接口声明依赖对象

如何实现依赖倒置原则:

每个类都尽量都有接口或抽象类,或者抽象类和接口都具备
变量的表面类型尽量是接口或抽象类
类尽量不要从具体类派生(不要超过两层)
尽量不要复写基类的方法(基类方法可能有依赖倒置,修改之后可能会导致难以预料的结果
结合里氏替换原则(父类能用的地方子类也可以用,详细见-里氏替换原则)

然而,并不是一直都不依赖细节,法律就必须要有细节的定义。用设计模式也要”审时度势“。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值