连载:面向对象葵花宝典:思想、技巧与实践(34) - DIP原则

DIP,dependency inversion principle,中文翻译为“依赖倒置原则”。

DIP是大名鼎鼎的Martin大师提出来的,他在1996 5月的C++ Reporter发表“ The Dependency Inversion Principle”的文章详细阐述了DIP原则,并且在他的经典著作《 Agile Software Development, Principles, Patterns》(中文翻译为:敏捷软件开发:原则、模式与实践)、《Practices, and Agile Principles, Patterns, and Practices in C#》(中文翻译为:敏捷软件开发:原则、模式与实践(C#版))中详细解释了DIP原则。

DIP原则主要有两点含义:

1) 高层模块不应该直接依赖低层模块,两者都应该依赖抽象层;

2) 抽象不能依赖细节,细节必须依赖抽象;

虽然DIP原则的解释非常清楚,但要真正理解也不那么简单,因为有几个关键的术语都比较抽象,我们需要更详细的解析:

1)什么是模块?

英文中用到了module、component,但我们这是在讲类的设计原则,为什么要把DIP拉进来呢?

其实Martin大师只是讲一个设计原则而已,这个原则可以应用到软件系统不同的层级。

例如:站在架构层的角度,模块可以指子系统subsystem

站在子系统的角度,模块可以指module,component

站在模块的角度:模块可以指类

所以说,这里的模块应该是一个广义的概念,而不是狭义的软件系统里各个子模块。

2)什么是依赖?

这里的依赖对应到具体的面向对象领域其实包含几个内容:

高层模块“依赖”低层模块:指高层模块需要调用低层模块的方法;

高层模块依赖抽象层:指高层模块基于抽象层编程;

低层模块依赖抽象层:指低层模块继承(inheritance)或者实现(implementation)抽象层;

细节依赖抽象:其实和上一个依赖是同一个意思;

所以说,大师就是大师啊,一个简简单单的“依赖”将各种情况都概括进来了,只是苦了我们这些平凡人,要么导致无法理解,要么导致理解错误:(

我们以一个简单样例来详细解释这些依赖,样例包含一个Player类,代表玩家;ICar接口,代表汽车;Benz、Ford、Chery代表具体的汽车,详细的代码如下

【Player】

package com.oo.oop.dip;

/**
 * 玩家,对应DIP中的“高层模块”
 *
 */
public class Player {

	/**
	 * 开福特
	 * 不好的依赖:对应DIP中的“高层模块依赖低层模块”,Player直接使用了Ford类对象作为参数,Ford类修改,Player类【需要】重新编译测试
	 */
	public void play(Ford car)
	{
		car.accelerate();
		car.shift();
		car.steer();
		car.brake();
	}

	/**
	 * 开奔驰
	 * 不好的依赖:对应DIP中的“高层模块依赖低层模块”,Player直接使用了Benz类对象作为参数,Benz类修改,Player类【需要】重新编译测试
	 */
	public void play(Benz car)
	{
		car.accelerate();
		car.shift();
		car.steer();
		car.brake();
	}

	/**
	 * 开奇瑞
	 * 不好的依赖:对应DIP中的“高层模块依赖低层模块”,Player直接使用了Chery类对象作为参数,Chery类修改,Player类【需要】重新编译测试
	 */
	public void play(Chery car)
	{
		car.accelerate();
		car.shift();
		car.steer();
		car.brake();
	}

	/**
	 * 开车
	 * 好的依赖: 对应DIP中的“高层模块依赖抽象层”,Player依赖ICar接口,不需要知道具体的车类型,Ford、Benz、Chery类修改,Player类【不需要】重新编译测试,只有ICar修改的时候Player才需要修改
	 */
	public void play(ICar car)
	{
		car.accelerate();
		car.shift();
		car.steer();
		car.brake();
	}

}

【ICar】

package com.oo.oop.dip;

/**
 * 汽车接口,对应DIP中的抽象层
 */
public interface ICar {

	/**
	 * 加速
	 */
	public void accelerate();

	/**
	 * 换挡
	 */
	public void shift();

	/**
	 * 转向
	 */
	public void steer();

	/**
	 * 刹车
	 */
	public void brake();
}

【Benz】

package com.oo.oop.dip;

/**
 * 奔驰,实现了ICar接口,对应DIP中的“低层依赖抽象层”
 *
 */
public class Benz implements ICar {

	@Override
	public void accelerate() {

		//加速非常快
		System.out.println("Benz accelerate: very fast !!");
	}

	@Override
	public void shift() {

		//自动挡
		System.out.println("Benz shift:  automatic transmission !!");
	}

	@Override
	public void steer() {

		//非常平稳
		System.out.println("Benz steer:  very smooth,ESP && DSC && VSC !!");
	}

	@Override
	public void brake() {

		//刹车辅助系统
		System.out.println("Benz steer:  ABS && EBA && BAS && BA !!");
	}

}

【Ford】

package com.oo.oop.dip;

/**
 * 福特,实现了ICar接口,对应DIP中的“低层依赖抽象层”
 *
 */
public class Ford implements ICar {

	@Override
	public void accelerate() {

		//加速快
		System.out.println("Ford accelerate: fast !!");
	}

	@Override
	public void shift() {

		//手自一体变速器
		System.out.println("Ford shift:  Tiptronic transmission !!");
	}

	@Override
	public void steer() {

		//平稳
		System.out.println("Ford steer:  smooth,ESP !!");
	}

	@Override
	public void brake() {

		//刹车辅助系统
		System.out.println("Ford steer:  ABS && EBA &!!");
	}

}

【Chery】

package com.oo.oop.dip;

/**
 * 奇瑞,实现了ICar接口,对应DIP中的“低层依赖抽象层”
 *
 */
public class Chery implements ICar {

	@Override
	public void accelerate() {

		//加速慢
		System.out.println("Chery accelerate: slow !!");
	}

	@Override
	public void shift() {

		//手动挡
		System.out.println("Chery shift:  manual transmission !!");
	}

	@Override
	public void steer() {

		//平稳
		System.out.println("Chery steer:  smooth,ESP && DSC !!");
	}

	@Override
	public void brake() {

		//刹车辅助系统
		System.out.println("Chery steer:  only ABS !!");
	}

}

连载:面向对象葵花宝典:思想、技巧与实践(34) - DIP原则,布布扣,bubuko.com

时间: 2024-12-15 01:51:39

连载:面向对象葵花宝典:思想、技巧与实践(34) - DIP原则的相关文章

连载:面向对象葵花宝典:思想、技巧与实践(33) - ISP原则

 ISP,Interface Segregation Principle,中文翻译为"接口隔离原则". 和DIP原则一样,ISP原则也是大名鼎鼎的Martin大师提出来的,他在1996年的C++ Reporter发表" The Interface Segregation Principle"的文章详细阐述了ISP原则,并且在他的经典著作< Agile Software Development, Principles, Patterns>(中文翻译为:敏捷

连载:面向对象葵花宝典:思想、技巧与实践(32) - LSP原则

LSP是唯一一个以人名命名的设计原则,并且作者还是一个"女博士"  ============================================================= LSP,Liskov substitution principle,中文翻译为"里氏替换原则". 这是面向对象原则中唯一一个以人名命名的原则,尽管Liskov在中国的知名度没有UNIX的几位巨匠(Kenneth Thompson.Dennis Ritchie).GOF四人帮那么

连载:面向对象葵花宝典:思想、技巧与实践(31) - OCP原则

开闭原则是一个大部分人都知道,但大部分人都不懂的设计原则! ==================================================================== OCP,Open-Closed Principle,中文翻译为"开闭原则". 当我第一次看到OCP原则时,我的感觉就是这原则也太抽象了吧,什么开,什么闭呢? 然后我去寻找更加详细的答案,最经典也是最常见的解释就是维基百科了: http://en.wikipedia.org/wiki/Open

连载:面向对象葵花宝典:思想、技巧与实践(36) - 设计原则如何用?

经过前面深入的阐述,SOLID的原则我们已经基本上讲清楚了,但如果想熟练的应用SOLID原则,仅仅知道SOLID是什么(what)还不够,我们还需要知道SOLID原则在什么时候和什么场景应用(when或where). 幸运的是,SOLID原则的5个独立原则在实际应用中基本上都是独挡一面,并不会在某个地方需要同时从可选的几个原则中挑选一个最优的原则来应用,这样大大降低了我们应用SOLID原则的难度. SOLID原则具体的应用场景如下: SRP原则:用于类的设计 当我们想出一个类,或者设计出一个类的

连载:面向对象葵花宝典:思想、技巧与实践(35) - NOP原则

NOP,No Overdesign Priciple,不要过度设计原则. 这应该是你第一次看到这个原则,而且你也不用上网查了,因为这个不是大师们创造的,而是我创造的:) 之所以提出这个原则,是我自己吃过苦头,也在工作中见很多人吃过类似的苦头. 你可能也见过这样的场景: 产品提出了一个需求,设计师眼光非常长远,他甚至把5年后可能的业务变化都提出来并且加以设计了,让你不得不佩服设计师的高瞻远瞩的眼光,并且由衷的从心底赞叹:牛逼啊! 但很快你就会发现,设计师是很牛逼,但你开发的时候就很苦逼了,设计方案

连载:面向对象葵花宝典:思想、技巧与实践(37) - 设计模式:瑞士军刀 or 锤子?

"设计模式"这个词几乎成为了软件设计的代名词,很多人非常天真的以为掌握了设计模式就掌握了软件设计,但实际上如果只是握了设计模式,软件设计的门都还没摸到! ======================================================== 谈起设计模式,那是几乎无人不知,无人不晓,大名鼎鼎的"GOF"(中文有的翻译为"四人帮")惊世之作,真是"平生不识GOF,学尽设计也枉然!" 然而,设计模式真的是

连载:面向对象葵花宝典:思想、技巧与实践(39) - 设计原则 vs 设计模式

又是设计原则,又是设计模式,到底该用哪个呢? ============================================================================= 在"设计模型"一章中,我们提到设计原则和设计模式是互补的,设计原则和设计模式互补体现在:设计原则主要用于指导"类的定义"的设计,而设计模式主要用于指导"类的行为"的设计. 举一个很简单的例子:假设我们要设计一个图形类Shape,这个类既支持三角形,

连载:面向对象葵花宝典:思想、技巧与实践(29) - 高内聚低耦合

高内聚低耦合,可以说是每个程序猿,甚至是编过程序,或者仅仅只是在大学里面学过计算机,都知道的一个简单的设计原则. 虽然如此流行和人所众知,但其实真正理解的人并不多,很多时候都是人云亦云. =============================================================== 要想真正理解"高内聚低耦合",需要回答两个问题: 1)为什么要高内聚低耦合? 2)高内聚低耦合是否意味内聚越高越好,耦合越低越好? 第一个问题:为什么要高内聚低耦合? 经典的

连载:面向对象葵花宝典:思想、技巧与实践(38) - 设计模式之道

很多人能够熟练背诵出所有的设计模式,能够快速画出各种设计模式的UML类图,也能够熟练的写出<设计模式>一书中各个模式的样例代码.但一到实际的项目设计和开发的时候,往往都会陷入迷茫:要么无从下手,不知道哪个地方要用设计模式:要么生搬硬套,胡乱使用设计模式,将方案和代码搞得一团乱麻. =========================================================================== [知易行难 -- 设计模式应用的问题] 形而下者谓之器,形而上者