代码实现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)呢?答案是可以。