四种关系,可以从强到弱为 依赖< 关联 <聚合 <组合,依赖很好判断,如果另个一个类的对象在引用类中表现为局部变量,方法参数、静态方法时候,判定为依赖。关联、聚合和组合需要根据上下文语义来定义。
首先看一看书上对这四种关系的定义:
- 依赖(Dependency)关系是类与类之间的联接。依赖关系表示一个类依赖于另一个类的定义。一般而言,依赖关系在Java语言中体现为局域变量、方法的形参,或者对静态方法的调用。(从使用以及生效范围来看,并不是单纯的定义,就算是定义为实例变量,但是使用上只在一个方法范围内使用,不在其他地方使用,也可以是依赖)
- 关联(Association)关系是类与类之间的联接,它使一个类知道另一个类的属性和方法(实例变量体现)。关联可以是双向的,也可以是单向的。两个类之前是一个层次的,不存在部分跟整体之间的关系。
- 聚合(Aggregation) 关系是关联关系的一种,是强的关联关系。聚合是整体和个体之间的关系。例如,汽车类与引擎类、轮胎类,以及其它的零件类之间的关系便整体和个体的关系。与关联关系一样,聚合关系也是通过实例变量实现的。但是关联关系所涉及的两个类是处在同一层次上的,而在聚合关系中,两个类是处在不平等层次上的,一个代表整体,另一个代表部分。
- 组合(Composition) 关系是关联关系的一种,是比聚合关系强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分对象的生命周期,组合关系是不能共享的。代表整体的对象需要负责保持部分对象和存活,在一些情况下将负责代表部分的对象湮灭掉。代表整体的对象可以将代表部分的对象传递给另一个对象,由后者负责此对象的生命周期。换言之,代表部分的对象在每一个时刻只能与一个对象发生组合关系,由后者排他地负责生命周期。部分和整体的生命周期一样。
以上关系的耦合度依次增强(关于耦合度的概念将在以后具体讨论,这里可以暂时理解为当一个类发生变更时,对其他类造成的影响程度,影响越小则耦合度越弱,影响越大耦合度越强)。由定义我们已经知道,依赖关系实际上是一种比较弱的关联,聚合是一种比较强的关联,而组合则是一种更强的关联,所以笼统的来区分的话,实际上这四种关系、都是关联关系。
依赖关系比较好区分,它是耦合度最弱的一种,在java中表现为局域变量、方法的形参,或者对静态方法的调用
package com.yjz.model;
//依赖(Dependency)关系是类与类之间的联接。依赖关系表示一个类依赖于另一个类的定义
//一般而言,依赖关系在Java语言中体现为局域变量、方法的形参,或者对静态方法的调用。
public class model_1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//依赖关系展示
Car car=new Car();
Driver driver=new Driver();
// 使用形参方式发生依赖关系
driver.drive1(car);
// 使用局部变量发生依赖关系
driver.drive2();
// 使用静态变量发生依赖关系
driver.drive3();
}
}
//汽车类
class Car {
public static void run() {
System.out.println("汽车在奔跑");
}
}
//司机类
//分别在不同方法中,方法参数、方法成员变量等局部变量的方式引用car类。构成弱耦合关系。
class Driver {
// 使用形参方式发生依赖关系
public void drive1(Car car) {
car.run();
}
// 使用局部变量发生依赖关系
public void drive2() {
Car car = new Car();
car.run();
}
// 使用静态变量发生依赖关系
public void drive3() {
Car.run();
}
}
关联关系在java中一般使用成员变量来实现,有时也用方法形参的形式实现。依然使用Driver和Car的例子,使用方法参数形式可以表示依赖关系,也可以表示关联关系,毕竟我们无法在程序中太准确的表达语义。
package com.yjz.model;
public class model_2 {
public static void main(String[] args) {
// 关联关系在java中一般使用成员变量来实现,有时也用方法形参的形式实现。
//关联(Association)关系是类与类之间的联接,它使一个类知道另一个类的属性和方法。关联可以是双向的,也可以是单向的
//即关联是一种比依赖强的耦合关系,他表示一个类使用到了另一个类的方法,就这个简单。如果作为全局变量,就是关联,局部变量,就是依赖了。
//当然,如果作为全局变量,但是在上下文的语义上,可以理解为更强的拥有关系,就是聚合或者耦合。
//可以说,聚合跟耦合是建立在关联关系的基础上的。
//如果两个类在一个层次上,就是关联,如果两个类属于整体跟部分,语义理解上的整体跟部分,比如汽车跟引擎,这就是聚合。
//如果在聚合的基础上,不只是整体跟部分那么简单,而且整体跟部分息息相关,整体控制部分的生死,部分在整体中起到至关重要,那就是组合关系、
Driver driver=new Driver();
driver.drive();
}
}
//汽车类
class Car {
public static void run() {
System.out.println("汽车在奔跑");
}
}
//司机类
class Driver {
// 使用成员变量形式实现关联
Car mycar;
public void drive() {
mycar.run();
}
// 使用方法参数形式实现关联
public void drive(Car car) {
car.run();
}
}
聚合关系是是一种比较强的关联关系,java中一般使用成员变量形式实现。对象之间存在着整体与部分的关系。
package com.yjz.model;
public class model_3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//首先,engine类作为car的全局变量,可以初步定义为是关联关系
//再看上下文语义,发现汽车的引擎跟汽车之间,是部分跟整体的部分,定义为聚合关系
//在看上下文,如果汽车坏了,引擎可以移植到其他汽车,引擎跟汽车只是聚合,汽车并不能掌控引擎生命周期的生死。不能定义为组合关系。
//即两者的生命周期并不同步
Car car=new Car();
car.run();
}
}
//引擎类
class engine{
public void doThing(){
System.out.println("发动引擎");
}
}
//汽车类
class Car{
engine e;
public void run(){
e.doThing();
}
}
组合关系是部分跟整体,而且部分整体之间紧密联系,拥有共同生命周期,整体控制部分的生命周期,整体消失时候,部分也会消失,部分消失时候,代表整体消失了,因为只有整体消失,部分才会消失,所以整体控制部分的生命周期。这种含义是上下文语义上的,即A跟B两个类在环境语义上的。并不代表在代码写作上的形式,比如上述聚合跟组合,代码结构一样,我们要看的是语言含义。
package com.yjz.model;
public class model_4 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//在这里,首先全局变量,推断至少是关联关系
//人跟心脏是部分跟整体,聚合
//人跟心脏,人死了心脏没了,心脏没了,人死。声明周期一致,组合。,最强拥有关系。
people p=new people();
p.life();
}
}
class heart{
public void run(){
System.out.println("我还活着");
}
}
class people{
heart h;
public void life(){
h.run();
}
}
所以,关联、聚合、组合只能配合语义,结合上下文才能够判断出来,而只给出一段代码让我们判断是关联,聚合,还是组合关系,则是无法判断的。