原则5-依赖倒置原则

代码实现java;

 

我们来实现一个功能:老张开车去东北;

public class LaoZhang

{

//the lao zhang is very poor,his car is Passat

public void Dirve(Passat pst){

pst.run();

}

 

public void Dest()

{

System.out.println("go to dong bei");

}

}

 

public class Passat

{

public void run()

{

System.out.println("passat begin to run!");

}

}

 

public class Client

{

public static void main(String[] args)

{

Driver lz= new LaoZhang();

Passat pst = new Passat();

lz.Dirve(pst);

lz.Dest();

}

}

 

没有问题,软件交付。一年后,老张中了彩票,换车了,换成了奔驰,然而从软件设计的角度上考虑,老张开不了奔驰,为啥,因为他只有开帕萨特的方法,是不是一脸懵逼!

 

不懵逼,我可以改,新建一个奔驰车类,然后给老张加个开奔驰的方法不就得了,也就是说,老张每换了一次车,就要修改LaoZhang类,添加开车方法,并且修改应用场景(main函数),可维护性大大降低,奔驰和帕萨特都提供的run()方法,相似度很高,但是你也复用不了,扩展就别说了,加一款车,所有的类都要改动。这种 被依赖者的变更竟然让依赖者来承担修改成本 的方式就影响了依赖倒置的原则;

 

依赖倒置原则描述如下:

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

也就是说,开发时考虑的都是如何针对抽象编程而不是针对细节编程;

采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,减少并行开发引起的风险,提高代码的可读性和可维护性。

我们基于依赖倒置原则重新实现 老张开车去东北,我们将开车进行抽象,具体什么车我们不管,所有的车都是调用run方法,具体是谁开车我们也不关心,反正就是开车和目的地两个方法,那么抽象有了:

public interface ICar

{

public void run();

}

public interface IDriver

{

public void Drive(ICar car);

public void Dest();

}

 

public class Passat implements ICar

{

public void run()

{

System.out.println("passat begin to run!");

}

}

 

public class LaoZhang implements IDriver

{

public void Drive(ICar car)

{

car.run();

}

 

public void Dest()

{

System.out.println("my dest is dong bei !");

}

}

 

public class Client

{

public static void main(String[] args)

{

IDriver driver= new LaoZhang();

ICar car = new Passat();

driver.Dirve(car);

driver.Dest();

}

}

 

这种情况下,老张不再依赖帕萨特,他们都依赖于抽象,如果换奔驰了,操作如下:

1、加个类

public class Benz implements ICar

{

public void run()

{

System.out.println("benz begin to run!");

}

}

2、然后你只需要在应用场景中将ICar car = new Passat() 改成 ICar car = new Benz()即可;driver类不受影响。

如果不是老张了,换成隔壁老王了,那么好办:

1、加个类

public class LaoWang implements IDriver

{

public void Drive(ICar car)

{

car.run();

}

 

public void Dest()

{

System.out.println("my dest is ge bi !");

}

}

2、然后你只需要在应用场景中将IDriver driver= new LaoZhang() 改成 IDriver driver= new LaoWang()即可,后面的drive和dest函数不用改,爽不爽!

 

 什么是并行开发的风险?并行开发最大的风险就是风险扩散,本来只是一段程序的错误或异常,逐步波及一个功能,一个模块,甚至到最后毁坏了整个项目,为什么并行开发就有这个风险呢?一个团队,20人开发,各人负责不同的功能模块,甲负责汽车类的建造,乙负责司机类的建造,在甲没有完成的情况下,乙是不能完全地编写代码的,缺少汽车类,编译器根本就不会让你通过!在缺少Benz类的情况下,Driver类能编译吗?更不要说是单元测试了!在这种不使用依赖倒置原则的环境中,所有的开发工作都是“单线程”的,甲做完,乙再做,然后是丙继续…,这在90年代“个人英雄主义”编程模式中还是比较适用的,一个人完成所有的代码工作,但在现在的大中型项目中已经是完全不能胜任了,一个项目是一个团队的协作结果,一个“英雄”再牛X也不可能了解所有的业务和所有的技术,要协作就要并行开发,要并行开发就要解决模块之间的项目依赖关系,那然后呢?依赖倒置原则就隆重出场了!只要制定出两者之间的接口(或抽象类)就可以独立开发了,而且项目之间的单元测试也可以独立的运行,而TDD(Test-Driven Development,测试驱动开发)开发模式就是依赖倒置原则的最高级应用。我们继续回顾上面司机驾驶汽车的例子,甲程序员负责IDriver的开发,乙程序员负责ICar的开发,两个开发人员只要制定好了接口就可以独立地开发了,甲开发进度比较快,完成了IDriver以及相关的实现类Driver的开发工作,而乙程序员滞后开发,那甲是否可以进行单元测试(Unit Test)呢?答案是可以。

你可能感兴趣的:(设计模式)