六大核心關係總覽
| 關係 | UML 符號 | 語意定義 | 程式碼映射 | 強度 |
| 泛化 | 實線 + 空心三角箭頭 → 父類 | 「is-a」關係,子類繼承父類所有結構與行為 | class Child extends Parent | ⭐⭐⭐⭐⭐ (最強) |
| 實現 | 虛線 + 空心三角箭頭 → 介面 | 類別實作介面契約 | class Impl implements Interface | ⭐⭐⭐⭐⭐ |
| 組合 | 實線 + 實心菱形 → 整體 | 「part-of」強擁有:部分與整體生命週期綁定,同生共死 | 成員變數,建構子中 new Part(),無公開 setter | ⭐⭐⭐⭐ |
| 聚合 | 實線 + 空心菱形 → 整體 | 「has-a」弱擁有:部分可獨立存在,可被多個整體共享 | 成員變數,透過建構子/Setter 注入 | ⭐⭐⭐ |
| 關聯 | 實線箭頭 (可雙向/單向/無向) | 結構性關係:一個類別知道另一個類別 | 成員變數 | ⭐⭐ |
| 依賴 | 虛線箭頭 → 被依賴者 | 臨時使用:方法參數、區域變數、靜態方法呼叫、拋出異常 | 方法簽名中出現 | ⭐ (最弱) |
關係強度排序 (強 → 弱)
泛化 = 實現 > 組合 > 聚合 > 關聯 > 依賴
關鍵區別深度解析
組合 vs 聚合:生命週期與擁有權
| 維度 | 組合 | 聚合 |
| 生命週期 | 整體銷毀 → 部分必定銷毀 | 部分可獨立存活,整體銷毀不影響部分 |
| 擁有權 | 獨佔擁有 | 共享擁有 |
| 建構方式 | 內部 new、工廠方法、Builder | 外部傳入 (DI)、Setter 注入 |
| 多重性 | 通常 1..1 或 1..* | 常見 *..* |
| 範例 | 人 ❤ 心臟、訂單 ❤ 訂單項、房子 ❤ 房間 | 學生 ◇ 老師、部門 ◇ 員工、汽車 ◇ 引擎 (可拆卸) |
關聯 vs 依賴:結構性 vs 臨時性
- 關聯:長期持有引用,屬於類別結構一部分。
class Order { Customer customer; }
- 依賴:方法執行期間臨時使用。
void process(Order order) { order.calculate(); }、List list = Arrays.asList(...)、throw new BusinessException()。
- 判斷口訣:成員變數 → 關聯/聚合/組合;方法參數/區域變數/靜態調用 → 依賴。
可見性與多重性標記
| 可見性 | 符號 | Java 對應 |
| public | + | public |
| private | - | private |
| protected | # | protected |
| package-private | ~ | 無修飾符 |
| 多重性 | 含義 | 範例 |
| 1 | 恰好一個 | Person 1 → 1 IdentityCard |
| 0..1 | 零或一個 | Employee 0..1 → ParkingSpace |
| * / 0..* | 零或多個 | Department * → Employee |
| 1..* | 一或多個 | Order 1..* → OrderItem |
| 3..5 | 三到五個 | PokerHand 5..5 → Card |
完整類別圖範例:電商訂單領域
@startuml
package "電商核心領域" {
class Customer {
- id: Long
- name: String
- email: String
+ placeOrder(): Order
}
class Order {
- id: Long
- status: OrderStatus
- createdAt: LocalDateTime
+ addItem(Product, int): void
+ calculateTotal(): BigDecimal
}
class OrderItem {
- quantity: int
- unitPrice: BigDecimal
+ getSubtotal(): BigDecimal
}
class Product {
- id: Long
- name: String
- price: BigDecimal
- stock: int
+ decreaseStock(int): void
}
enum OrderStatus {
PENDING, PAID, SHIPPED, DELIVERED, CANCELLED
}
' 關係
Customer "1" -- "*" Order : 下單 >
Order "*" -- "1..*" OrderItem : 包含 >
OrderItem "1" -- "1" Product : 引用 >
Order "1" -- "1" Payment : 付款 >
Order "1" -- "1" Shipment : 出貨 >
' 組合:訂單項隨訂單銷毀
Order *-- OrderItem
' 聚合:商品可被多訂單引用
OrderItem o-- Product
}
@enduml
PlantUML 關係語法速查
| 關係 | 語法 | 範例 |
| 泛化 | Parent <|-- Child | Animal <|-- Cat |
| 實現 | Interface <|.. Impl | Serializable <|.. User |
| 組合 | Whole *-- Part | Order *-- OrderItem |
| 聚合 | Whole o-- Part | | Department o-- Employee |
| 關聯 | A -- B (可加箭頭 -->、標籤 : label、多重性 "1" -- "*") | Customer "1" -- "*" Order |
| 依賴 | A ..> B | OrderService ..> OrderRepository |
常見建模錯誤與修正
| 錯誤 | 問題 | 修正 |
| 把關聯畫成組合 | 訂單與客戶是組合?客戶刪除訂單不應消失 | 改為關聯 (單向/雙向) |
| 忽略依賴關係 | Service 依賴 Repository、Util、Exception 未畫 | 補上虛線箭頭,展現架構分層 |
| 多重性標記錯誤 | 訂單項 0..*?至少 1 項 | 改為 1..* |
| 箭頭方向反了 | 泛化箭頭指向子類 | 空心三角指向父類/介面 |
| 類別圖塞滿細節 | 所有 getter/setter 列出,圖表不可讀 | 僅保留核心屬性/方法,隱藏細節 |
最佳實踐建議
- 先識別核心領域概念 (實體、值物件、聚合根),再畫關係。
- 聚合根邊界 內部用組合,跨聚合根用關聯/依賴。
- 依賴倒置:高層模組不依賴低層實現,依賴抽象介面 (虛線實現箭頭)。
- 版本控制圖表原始碼 (PlantUML/Mermaid),代碼與文檔同步演進。
- 分層繪圖:領域模型圖、架構分層圖、序列圖分開,各司其職。