代码改变世界

依赖和耦合

2017-11-16 13:30  dengchaojie_learner  阅读(1672)  评论(0编辑  收藏  举报

依赖和耦合的最大区别在于,当我们说“A和B耦合”时,在字面含义中,A和B二者平等。
然而,正确的模块关系根本不应该平等,而应该是单向依赖才对。
所以我们应该说“A依赖B”,这样含义要清楚得多。
A依赖B意味着,A模块可以调用B模块暴露的API,但B模块绝不允许调用A模块的API。
单向依赖是红线,好的设计一定不会违反这条红线。

注意:根据实质重于形式原则,本文中的“依赖”指人脑中的依赖而不是编译器的依赖。
只要程序员编写模块A时,需要知道模块B的存在,需要知道模块B提供哪些功能,A对B依赖就存在。

但是我们改用“依赖”术语后,我们就发现单向依赖不是坏事,根本不必费心消除,
因为,真正的重点是,依赖关系中,被依赖方暴露的接口能不能足够“正交”和“紧凑”。

正交性是指一个模块提供的API中,多个方法之间是否有重复的功能。
如果有重复功能,正交性就差。
通常,正交性高的模块更稳定,不会因为上层业务变化而被迫修改代码。
好的API内部的多个方法之间不应该有任何重复功能,只实现正交的机制。

如果感觉拆得太细使用不便,应该在底层API之外包装出一层Helper、Utility组成的胶水层。
胶水层调用底层原语API来实现常用模式供上层使用。
对于胶水层中的模块,对正交性的要求可以稍低一些。
注意上层代码既可以直接调用正交的底层API,又可以调用胶水层的常用模式。

紧凑性是指一个模块提供的API中,公有方法总数必须很少,每个方法的参数也必须很少。
《Unix编程艺术》上说一个模块不要超过7个方法,不然就很难理解。
但我实践中发现,我一般编写的模块,公有方法通常不超过3个。

 

java中如何准确的体现依赖、关联、聚合和组合。

首先看一看书上对这四种关系的定义:

  • 依赖(Dependency)关系是类与类之间的联接。依赖关系表示一个类依赖于另一个类的定义。例如,一个人(Person)可以买车(car)和房子(House),Person类依赖于Car类和House类的定义,因为Person类引用了Car和House。与关联不同的是,Person类里并没有Car和House类型的属性,Car和House的实例是以参量的方式传入到buy()方法中去的。一般而言,依赖关系在Java语言中体现为局域变量、方法的形参,或者对静态方法的调用。
  • 关联(Association)关系是类与类之间的联接,它使一个类知道另一个类的属性和方法。关联可以是双向的,也可以是单向的。在Java语言中,关联关系一般使用成员变量来实现。
  •  聚合(Aggregation) 关系是关联关系的一种,是强的关联关系。聚合是整体和个体之间的关系。例如,汽车类与引擎类、轮胎类,以及其它的零件类之间的关系便整体和个体的关系。与关联关系一样,聚合关系也是通过实例变量实现的。但是关联关系所涉及的两个类是处在同一层次上的,而在聚合关系中,两个类是处在不平等层次上的,一个代表整体,另一个代表部分。
  •  组合(Composition) 关系是关联关系的一种,是比聚合关系强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分对象的生命周期,组合关系是不能共享的。代表整体的对象需要负责保持部分对象和存活,在一些情况下将负责代表部分的对象湮灭掉。代表整体的对象可以将代表部分的对象传递给另一个对象,由后者负责此对象的生命周期。换言之,代表部分的对象在每一个时刻只能与一个对象发生组合关系,由后者排他地负责生命周期。部分和整体的生命周期一样。

——摘自《Java面向对象编程》,作者:孙卫琴

       以上关系的耦合度依次增强(关于耦合度的概念将在以后具体讨论,这里可以暂时理解为当一个类发生变更时,对其他类造成的影响程度,影响越小则耦合度越弱,影响越大耦合度越强)。由定义我们已经知道,依赖关系实际上是一种比较弱的关联,聚合是一种比较强的关联,而组合则是一种更强的关联,所以笼统的来区分的话,实际上这四种关系、都是关联关系。



链接:
https://www.zhihu.com/question/21386172/answer/54476702
https://wenku.baidu.com/view/478e2dea856a561252d36fa9.html
http://blog.csdn.net/zhengzhb/article/details/7190158