依赖(Dependency)
- 含义:一个类的变化会影响到另一个类,但反之不一定。这是一种"使用"关系,通常是临时的、较弱的。
- 典型场景 :一个类作为另一个类方法的局部变量 、方法参数 ,或调用静态方法。
- UML表示 :带箭头的虚线,箭头指向被依赖的类(即"使用者"指向"被使用者")。

- 代码示例:
java
// 动物类 依赖于 水类(喝水方法需要用水对象作为参数)
public class Animal {
public void drink(Water w) { // 作为方法参数
System.out.println(w.getName());
}
}
关联(Association)
- 含义:一个对象知道另一个对象的长期存在。这是一种"拥有"或"知道"的关系,比依赖更强、更持久。
- 典型场景:一个类以"成员变量(属性)"的形式保存对另一个类的引用。
- UML表示 :实线 ,通常带箭头指向被关联的类(双向关联可以没有箭头或有双向箭头)。可以标注多重性(如 1, 0.., 1.. 等)。

- 代码示例:
java
public class Person
{
private Book _book; // 单向关联
public Person(Book book)
{
_book = book;
}
public void Read()
{
Console.WriteLine($"Reading: {_book.Title}");
}
}
public class Book
{
public string Title { get; set; }
public Book(string title)
{
Title = title;
}
}
聚合(Aggregation) 和 组合(Composition) 确实都是关联关系(Association) 的特殊形式。
聚合(Aggregation)
特点 :是整体与部分 的关系,且部分可以离开整体而单独存在(如"汽车"和"轮胎")。
场景:汽车有轮子,但轮子可以拆下来装到别的车上。
UML表示 :带空心菱形的实线,菱形指向整体。


cs
public class Car
{
public string Model { get; set; }
private List<Wheel> _wheels = new List<Wheel>(); // 聚合
public void AddWheel(Wheel wheel)
{
_wheels.Add(wheel);
wheel.SetCar(this);
}
public void RemoveWheel(Wheel wheel)
{
_wheels.Remove(wheel);
wheel.RemoveCar();
}
}
public class Wheel
{
public string Brand { get; set; }
public int Size { get; set; }
private Car _car; // 可选的反向引用
public void SetCar(Car car) => _car = car;
public void RemoveCar() => _car = null;
}
组合(Composition)
特点 :是整体与部分 的关系,但部分不能离开整体而单独存在。同生同灭。
场景:如公司和部门是组合关系,没有公司就不存在部门。
**UML表示:**带实心(黑色实心:要死一起死,良心是黑的)菱形的实线,菱形指向整体。


cs
public class Order
{
public int OrderId { get; set; }
private List<OrderItem> _items = new List<OrderItem>(); // 组合
public void AddItem(string productName, int quantity, decimal price)
{
// OrderItem 的创建和销毁完全由 Order 控制
var item = new OrderItem(productName, quantity, price);
_items.Add(item);
}
public decimal GetTotal()
{
return _items.Sum(i => i.GetSubtotal());
}
~Order()
{
// 订单销毁时,OrderItem 也会被销毁(GC 回收)
Console.WriteLine($"Order {OrderId} disposed, items also disposed");
}
}
public class OrderItem
{
public string ProductName { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public OrderItem(string productName, int quantity, decimal price)
{
ProductName = productName;
Quantity = quantity;
UnitPrice = price;
}
public decimal GetSubtotal() => Quantity * UnitPrice;
}
泛化(Generalization)
- 含义 :即面向对象的继承关系。子类继承父类的属性和方法。
- 典型场景:普通类继承普通类,或抽象类继承抽象类。
- UML表示 :空心三角形 + 实线,空心三角形指向父类。

- 代码示例:
java
// 父类
public class Animal {
public void eat() {}
}
// 子类 泛化 父类
public class Dog extends Animal {
public void bark() {}
}
实现(Realization)
- 含义:类实现接口。类遵循接口定义的契约,实现其所有方法。
- 典型场景:一个普通类实现一个或多个接口。
- UML表示 :空心三角形 + 虚线,空心三角形指向接口。

- 代码示例:
java
// 接口
public interface Flyable {
void fly();
}
// 鸟类 实现 飞行接口
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("Bird flying...");
}
}
关系强弱排序
在UML(统一建模语言)中,这六种关系(依赖、关联、聚合、组合、泛化、实现)从语义强度(即类与类之间联系的紧密程度、耦合度高低、依赖性大小)来看,通常的排序由弱到强如下:
强弱排序(从最弱到最强)
依赖 < 关联 < 聚合 < 组合 < 实现 < 泛化
另一种常见视角 (从代码修改的影响范围看):泛化 和实现 的耦合度最高,因为它们直接决定了类的结构和契约;而组合虽然整体-部分关系极强,但往往封装在内部,对外部的耦合扩散有时弱于继承。
- 依赖(最弱)
- 特点:仅仅是临时性的"使用"关系。一个类的变化可能会影响另一个类,但反过来不成立。
- 典型形式:局部变量、方法参数、静态方法调用。
- 强度理由:被依赖者并不作为使用者的长期状态存在,生命周期短暂。
- 关联(弱)
- 特点:长期持有的"知道/拥有"关系。一个类以成员变量形式引用另一个类。
- 强度理由:比依赖强,因为被关联者是类的一部分状态,但双方生命周期独立,可以单独存在。
- 聚合(中弱)
- 特点:特殊的关联,表示"整体-部分"关系,但部分可以脱离整体独立存在。
- 例子:汽车(整体)与轮胎(部分)。轮胎拆下来仍可装到别的车上。
- 强度理由:比普通关联强,因为有明确的整体-部分语义,但生命周期独立。
- 组合(中强)
- 特点:更强的"整体-部分"关系,部分的生命周期由整体控制,不能单独存在。
- 例子:人(整体)与心脏(部分)。心脏脱离人体即失去意义。
- 强度理由:比聚合强,因为整体负责创建和销毁部分,耦合度更高。
5. 实现(强)
- 特点:类与接口之间的契约关系。实现类必须遵守接口的全部约定。
- 强度理由:实现类依赖于接口定义的稳定契约,如果接口改变,所有实现类都受影响。比起组合,它对系统架构的约束更广泛。
6. 泛化(最强)
- 特点:继承关系,子类完全依赖于父类的实现细节(即便使用里氏替换原则,也存在白盒复用)。
- 强度理由 :这是最强的耦合关系。父类的一个方法修改,可能波及所有子类;且子类无法分离对父类的依赖。因此被公认强度最高。
- 设计原则警示 :面向对象设计原则中提倡"组合优于继承 "(
Composition over Inheritance),正是因为泛化(继承)的耦合度太强
