首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

UML 類圖六大關係深度解析:泛化、實現、依賴、關聯、聚合、組合 — 圖解+代碼映射+強弱排序

     編輯:Java 綜合教學

UML 類圖六大關係全景指南:從符號到代碼落地的完整映射

UML 類圖是物件導向設計的藍圖,六大關係 (泛化、實現、依賴、關聯、聚合、組合) 定義了類之間的靜態結構與語義綁定強度。本文採用「符號圖解 → 語義定義 → 代碼映射 → 典型案例 → 強弱排序」五維度,助你徹底搞懂每種關係的本質與工程落地差異。

一、六大關係速查表

關係語義UML 符號代碼映射典型例子強度
泛化繼承,is-a實線空心三角箭頭 → 父類class Child extends Parent老虎 → 動物最強
實現接口實現虛線空心三角箭頭 → 接口class Impl implements InterfaceArrayList → List最強
組合強整體-部分,同生共死實線實心菱形 → 整體成員變量 + 構造器初始化 + 生命週期綁定公司 ↔ 部門強
聚合弱整體-部分,部分可獨立實線空心菱形 → 整體成員變量 + setter/構造器注入汽車 ↔ 輪胎、公司 ↔ 員工中
關聯平級長期引用實線箭頭 → 被引用方成員變量師生、夫妻、訂單-用戶中弱
依賴臨時使用、參數/局部變量/靜態方法調用虛線箭頭 → 被依賴方方法參數、局部變量、靜態方法調用老師 → 課程 (授課時用)最弱

二、逐個關係深度拆解

1. 泛化 — 繼承體系的基石

  • 語義:子類繼承父類所有非 private 結構與行為,可擴展、可覆寫。
  • 代碼:public class Tiger extends Animal {}
  • 設計原則:里氏替換原則 (LSP) — 父類出現的地方必須能透明替換為子類。濫用繼承導致「脆弱基類問題」,優先考慮組合/委派。

2. 實現 — 契約與實現分離

  • 語義:類承諾履行接口定義的契約,一個類可實現多個接口。
  • 代碼:public class ArrayList implements List, RandomAccess, Cloneable, Serializable {}
  • 關鍵點:接口定義「做什麼」,實現類決定「怎麼做」;面向接口編程降低耦合。

3. 依賴 — 最脆弱的耦合

  • 語義:A 臨時使用 B,B 變更可能影響 A,但無長期持有關係。
  • 代碼形式:
    1. 方法參數:void teach(Course c)
    2. 局部變量:void m() { Tool t = new Tool(); t.use(); }
    3. 靜態方法調用:Utils.format(date)
  • 治理建議:減少雙向依賴、避免循環依賴、依賴抽象而非具體類 (DIP)。

4. 關聯 — 平級長期持有

  • 語義:雙方地位對等,長期持有引用,可單向/雙向、一對一/一對多/多對多。
  • 代碼:class Teacher { List students; } / class Student { Teacher advisor; }
  • 導航性:箭頭表示可導航方向;無箭頭 = 雙向。
  • 多重性:1, *, 0..1, 1..* 等標註在關聯線旁。

5. 聚合 — 「Has-a」共享所有權

  • 語義:整體包含部分,但部分可屬於多個整體、生命週期獨立。
  • 代碼:class Car { Set wheels; void addWheel(Wheel w) { wheels.add(w); } } — Wheel 可被多輛車共享 (理論上),車銷毀 Wheel 存活。
  • 區分關鍵:語義層面「整體-部分」;代碼層面與關聯相同 (均為成員變量),僅靠業務語義區分。

6. 組合 — 「Contains-a」獨佔所有權

  • 語義:整體獨佔部分,部分不可共享、隨整體創建銷毀。
  • 代碼落地模式:
    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();
        }
    }
  • 關鍵約束:部分無獨立構造器公開、無 setter 暴露、整體負責完整生命週期管理。

三、聚合 vs 組合:工程落地的決策樹

  1. 部分能否脫離整體獨立存在/被其他整體共享? → 是 → 聚合 / 否 → 組合
  2. 整體刪除時,部分是否必須級聯刪除? → 是 → 組合
  3. 業務上是否存在「部分轉移到另一整體」場景? → 是 → 聚合

經驗法則:寧可先用關聯/聚合,業務明確要求強生命週期綁定時再升級為組合。過早用組合會限制領域模型靈活性 (如部門重組、輪胎更換)。

四、關聯 vs 依賴:邊界劃分

維度關聯依賴
持有時間長期 (對象生命週期級)短期 (方法調用級)
代碼位置成員變量參數/局部變量/靜態調用
語義強度業務級長期關係技術級臨時使用
變更影響結構性影響實現細節影響

五、綜合案例:電商訂單領域模型

// 泛化
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(), "您的訂單已發貨"); } }

六、強弱排序總結與設計建議

強度排序:泛化 = 實現 > 組合 > 聚合 > 關聯 > 依賴

  • 高強度 (泛化/實現/組合):構建領域核心骨架,變更成本高,需審慎設計、充分測試。
  • 中強度 (聚合/關聯):表達業務實體間長期協作,保持低耦合、高內聚。
  • 低強度 (依賴):實現細節層面的協作,遵循「依賴倒置」,依賴抽象接口而非具體類。

黃金法則:優先使用關聯/聚合表達業務關係;生命週期強綁定才用組合;行為復用優先組合/委派,非必要不繼承;跨層調用只依賴接口。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved