UML 中四种关系的深度辨析
在面向对象设计中,理清类之间的关系至关重要。UML 提供了四种主要关系:依赖(Dependency)、关联(Association)、聚合(Aggregation)和组合(Composition)。它们之间的耦合度由弱到强,理解它们的区别能帮助我们写出更松耦合的代码。
依赖关系(Dependency)
依赖是最弱的关系,通常用虚线箭头表示。它意味着一个类的变化可能会影响另一个类,但两者之间没有长期的持有关系。生成代码时,依赖方不会将对方作为属性存储。
在实际编码中,依赖通常表现为以下三种形式:
- 临时变量:方法内部实例化并使用。
- 参数传递:作为方法的入参。
- 返回值:作为方法的返回结果。
以'动物'依赖'水'为例,如果水是局部变量,它的生命周期仅限于方法执行期间:
public class Animal {
public void growUp() {
Water water = new Water();
// 使用 water
}
}
注意,这里 Animal 类本身并没有 water 属性,一旦 growUp 方法结束,water 对象即被销毁。这种短暂的生命周期是依赖关系的核心特征。
关联关系(Association)
关联比依赖更强,用实线表示。它意味着一个类持有另一个类的引用作为属性,双方存在长期的认知关系。
例如,'水'与'气候'是关联的。在代码层面,这体现为属性注入:
public class Water {
private Climate climate; // 持有引用
}
关联分为单向和双向:
- 单向关联:源类知道目标类,反之不然。
- 双向关联:双方互相持有对方的引用。
从生命周期看,关联关系随着对象的创建而建立,随对象销毁而结束,比依赖关系持久得多。
聚合与组合(Aggregation & Composition)
这两者都是特殊的关联关系,常被混淆。区分的关键在于生命周期和所有权。
聚合(Aggregation)
聚合表示'拥有'关系,但部分可以独立于整体存在。比如'雁群'拥有'大雁',但大雁可以离开雁群单独飞行。
代码实现上,聚合对象通常在构造函数中接收外部传入的实例:
public class {
List<Goose> geese;
{
.geese = geese;
}
}


