依赖倒置原则(Dependence Invsersion Principle,DIP):High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.
翻译过来,包含三层含义:(1)高层模块不应该依赖低层模块,两者都应该依赖其抽象(2)抽象不应该依赖细节(3)细节应该依赖抽象。
高层模块和低层模块容易理解,每一个逻辑的实现都是由原子逻辑组成的,不可分割的原子逻辑就是低层模块,原子逻辑的再组装就是高层模块。那什么事抽象?什么又是细节呢?在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点就是可以直接被实例化,也就是可以加上一个关键字new产生一个对象,依赖倒置原则在java语言中的表现就是:
(1)模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的
(1)模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的
(2)接口或抽象类不依赖于实现类
(3)实现类依赖接口或抽象类。
更加精简的定义就是"面向接口编程"——OOD(Object-Oriented Design,面向对象设计)的精髓之一。
采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。
在Java中,只要定义变量就必然要有类型,一个变量可以有两种类型:表面类型和实际类型,表面类型是在定义的时候赋予的类型,实际类型是对象的类型。
抽象是对实现的约束,对依赖者而言,也是一种契约,不仅仅约束自己,还同时约束自己与外部的关系,其目的是保证所有的细节不脱离契约的范畴,确保约束双方按照既定的契约(抽象)共同发展,只要抽象这根基线在,细节就脱离不了这个圆圈,始终让你的对象做到“言必信,行必果”。
依赖的三种写法:(1)构造函数传递依赖对象(2)Setter方法传递依赖对象(3)接口声明依赖对象。
练习代码:
package com.gc.designmodel;
/**
*
* @说明 学习设计模式之依赖倒置原则(Dependence Inversion Principle,DIP)
* @作者 GeneralAndroid
* @创建日期 2015-9-1 下午1:13:12
* @版本号 1.0
* @since 1.0
* 采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和
* 可维护性。
*
* 依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合。
* 在项目中使用时只要遵循以下的几个规则就可以:
* (1)每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备。
* (2)变量的表面类型尽量是接口或者是抽象类
* (3)任何类都不应该从具体类派生(主要不超过两层的继承还是可以忍受的)
* (4)尽量不要覆写基类的方法
* (5)结合里式替换原则使用
*
*/
public class TestDIPDemo {
public static void main(String[] args) {
//
// Driver1 zhangSan=new Driver1();
// Benz1 benz=new Benz1();
// //张三开奔驰车
// zhangSan.drive(benz);
// IDriver zhangSan=new Driver();
// ICar benz=new Benz();
// zhangSan.drive(benz);
// ICar bmw=new BMW();
// zhangSan.drive(bmw);
// IDriverOne iDriverOne=new DriverOne(new Benz());
// iDriverOne.drive();
IDriverTwo iDriverTwo=new DriverTwo();
iDriverTwo.setCar(new Benz());
iDriverTwo.drive();
}
}
/**司机类**/
class Driver1
{
/**司机的主要职责就是驾驶汽车**/
public void drive(Benz1 benz)
{
benz.run();
}
}
/**奔驰车类**/
class Benz1{
/**汽车肯定会跑**/
public void run(){
System.out.println("奔驰汽车开始运行...");
}
}
/**宝马车类**/
class BMW1{
/**宝马车当然也可以开动了**/
public void run(){
System.out.println("宝马汽车开始运行...");
}
}
/**接口只是一个抽象化的概念,是对一类事物的最抽象描述,具体的实现代码由相应的实现类来完成。
* 依赖3种写法的其中一种——接口声明依赖对象。
* **/
/**司机接口**/
interface IDriver{
/**是司机就应该会驾驶汽车**/
public void drive(ICar car);
}
/**司机实现类**/
class Driver implements IDriver{
/**司机的主要职责就是驾驶汽车**/
public void drive(ICar car) {
// TODO Auto-generated method stub
car.run();
}
}
/**汽车接口**/
interface ICar{
/**是汽车就应该能跑**/
public void run();
}
class Benz implements ICar{
public void run() {
// TODO Auto-generated method stub
System.out.println("奔驰汽车开始运行...");
}
}
class BMW implements ICar{
public void run() {
// TODO Auto-generated method stub
System.out.println("宝马汽车开始运行...");
}
}
/***依赖的三种写法***/
/**1、构造函数传递依赖对象:
* 在类中通过构造函数声明依赖对象,按照依赖注入的说法,这种方式叫做构造函数注入。
* **/
interface IDriverOne
{
//是司机就应该会驾驶汽车
public void drive();
}
class DriverOne implements IDriverOne{
private ICar car;
//构造函数注入
public DriverOne(ICar _car){
this.car=_car;
}
//司机的主要职责就是驾驶汽车
public void drive() {
// TODO Auto-generated method stub
this.car.run();
}
}
/**2、Setter方法传递依赖对象
* 在抽象中设置Setter方法声明依赖关系,依照依赖注入的说法,这是Setter依赖注入
* **/
interface IDriverTwo{
/**车辆型号**/
public void setCar(ICar car);
/**是司机就应该会驾驶汽车**/
public void drive();
}
class DriverTwo implements IDriverTwo{
private ICar car;
public void setCar(ICar car) {
// TODO Auto-generated method stub
this.car=car;
}
/**司机的主要职责就是驾驶汽车**/
public void drive() {
// TODO Auto-generated method stub
this.car.run();
}
}
转载请注明出处: http://blog.csdn.net/gc_gongchao/article/details/48194027