UML 類圖是物件導向設計的藍圖,六大關係 (泛化、實現、依賴、關聯、聚合、組合) 定義了類之間的靜態結構與語義綁定強度。本文採用「符號圖解 → 語義定義 → 代碼映射 → 典型案例 → 強弱排序」五維度,助你徹底搞懂每種關係的本質與工程落地差異。
| 關係 | 語義 | UML 符號 | 代碼映射 | 典型例子 | 強度 |
|---|---|---|---|---|---|
| 泛化 | 繼承,is-a | 實線空心三角箭頭 → 父類 | class Child extends Parent | 老虎 → 動物 | 最強 |
| 實現 | 接口實現 | 虛線空心三角箭頭 → 接口 | class Impl implements Interface | ArrayList → List | 最強 |
| 組合 | 強整體-部分,同生共死 | 實線實心菱形 → 整體 | 成員變量 + 構造器初始化 + 生命週期綁定 | 公司 ↔ 部門 | 強 |
| 聚合 | 弱整體-部分,部分可獨立 | 實線空心菱形 → 整體 | 成員變量 + setter/構造器注入 | 汽車 ↔ 輪胎、公司 ↔ 員工 | 中 |
| 關聯 | 平級長期引用 | 實線箭頭 → 被引用方 | 成員變量 | 師生、夫妻、訂單-用戶 | 中弱 |
| 依賴 | 臨時使用、參數/局部變量/靜態方法調用 | 虛線箭頭 → 被依賴方 | 方法參數、局部變量、靜態方法調用 | 老師 → 課程 (授課時用) | 最弱 |
public class Tiger extends Animal {}public class ArrayList implements List, RandomAccess, Cloneable, Serializable {} void teach(Course c)void m() { Tool t = new Tool(); t.use(); }Utils.format(date)class Teacher { List students; } / class Student { Teacher advisor; }1, *, 0..1, 1..* 等標註在關聯線旁。class Car { Set wheels; void addWheel(Wheel w) { wheels.add(w); } } — Wheel 可被多輛車共享 (理論上),車銷毀 Wheel 存活。public final class Company {
private final List departments = new ArrayList<>();
public Company() {
departments.add(new Department("研發", this)); // 構造器內創建,傳 this 建立反向引用
departments.add(new Department("市場", this));
}
public void dissolve() { // 整體銷毀
departments.forEach(Department::shutdown);
departments.clear();
}
}
經驗法則:寧可先用關聯/聚合,業務明確要求強生命週期綁定時再升級為組合。過早用組合會限制領域模型靈活性 (如部門重組、輪胎更換)。
| 維度 | 關聯 | 依賴 |
|---|---|---|
| 持有時間 | 長期 (對象生命週期級) | 短期 (方法調用級) |
| 代碼位置 | 成員變量 | 參數/局部變量/靜態調用 |
| 語義強度 | 業務級長期關係 | 技術級臨時使用 |
| 變更影響 | 結構性影響 | 實現細節影響 |
// 泛化
abstract class Payment {}
class AlipayPayment extends Payment {}
class WechatPayment extends Payment {}
// 實現
interface OrderRepository { Order findById(Long id); }
class MyBatisOrderRepository implements OrderRepository {}
// 組合
class Order {
private final List items = new ArrayList<>(); // 訂單銷毀,明細必刪
public void addItem(Product p, int qty) { items.add(new OrderItem(p, qty)); }
}
// 聚合
class Customer {
private final Set addresses = new HashSet<>(); // 地址可被多用戶引用(家庭共用),用戶刪除地址保留
public void addAddress(Address a) { addresses.add(a); }
}
// 關聯
class Order {
private Customer customer; // 長期引用,雙向導航
private Payment payment;
}
// 依賴
class OrderService {
public void notify(Order order, NotificationChannel channel) { // channel 臨時傳入
channel.send(order.getCustomer().getContact(), "您的訂單已發貨");
}
}
強度排序:泛化 = 實現 > 組合 > 聚合 > 關聯 > 依賴
黃金法則:優先使用關聯/聚合表達業務關係;生命週期強綁定才用組合;行為復用優先組合/委派,非必要不繼承;跨層調用只依賴接口。