💡 注意:所有圖示均以PlantUML格式提供。您可使用Visual Paradigm 圖示即程式碼.
🔹 UML 簡介
什麼是 UML?
「統一模型語言(UML)是一種通用的視覺化建模語言,用於指定、視覺化、建構和文件化軟體系統的各項產物。」 — Rumbaugh 等人,1999
主要特徵:
-
🎨 視覺符號:用於建模系統的圖形語法
-
📐 標準化:自1997年起由對象管理組織(OMG)採用的標準
-
🔧 語言,而非方法:定義符號,而非流程
-
🌐 範圍廣泛:可建模業務流程、系統功能、程式碼結構與資料庫結構
UML 不是什麼
| 誤解 | 事實 |
|---|---|
| 一種開發方法論 | 僅是一種建模符號 |
| 一種程式語言 | 抽象規格語言 |
| 僅適用於物件導向程式設計 | 適用於資料庫、商業模型等 |
| 在所有方面都精確定義 | 早期版本中仍存在一些語義上的模糊性 |
🔹 歷史與標準化
演進時間軸

1965-1970:Simula-67(第一種物件導向語言)
↓
1970年代-1980年代:Xerox PARC 的 Smalltalk
↓
1984:Bjarne Stroustrup 發表 C++
↓
1988-1992:物件導向方法的蓬勃發展(Booch、OMT、OOSE 等)
↓
1994:Rumbaugh 加入 Rational 的 Booch → 統一工作開始
↓
1995:UML 0.8 草案發布
↓
1996:OMG 發出標準建模語言的 RFP
↓
1997:OMG 採納 UML 1.1(11 月 14 日)
↓
2000:UML 1.3 正式發佈
↓
2003:UML 1.5 發佈;UML 2.0 超結構被接受
為何 UML 獲勝「方法之戰」
-
整合了超過 50 種競爭性的物件導向方法為一種標準
-
獲得主要產業參與者(IBM、Microsoft、Oracle、HP)的支持
-
提供擴展機制以支援客製化
-
成為物件導向建模的事實標準
⚠️ 批判性觀點:有人認為 UML 是「由委員會設計的怪物語言」,早期版本語義不精確。
🔹 類別與屬性
類別結構
UML 類別以最多三個區段的矩形來表示。

@startuml
class Student {
firstName: String
lastName: String
email[0..1]: String
encryptedPW: String
+ totalPoints(): Integer
+ setPassword(pw: String)
+ checkPW(pw: String): Boolean
}
@enduml
屬性宣告語法
[存取權限] 名稱[多重性]: 類型 [= 預設值] {屬性}
PlantUML 範例:

@startuml
class Student {
+ ProgramOfStudy[0..2]: String = "MIS"
- encryptedPW: String {frozen}
# internalID: Integer
~ packagePrivateData: String
}
@enduml
屬性範圍
-
實例範圍 (預設): 每個物件都有其自身的值
-
類別範圍 (靜態): 所有實例共享的單一值

@startuml
class Student {
name: String
{static} count: Integer
}
@enduml
UML 中的鍵 ⚠️
重要限制: UML 沒有內建的鍵概念。可使用範型或標記值作為替代方案。

@startuml
class Student {
{pk} id: Integer
{ak1} email: String
- name: String
}
@enduml
🔹 關聯與關係
基本關聯與多重性
@startuml
class Exercise
class Chapter
Exercise "0..*" -- "1..1" Chapter : 屬於
@enduml
解釋: 每個練習僅屬於一個章節;一個章節可包含零個或多個練習。
角色名稱
除了(或除了)關聯名稱外,可在關聯端使用角色名稱:
@startuml
class Person
class Company
Person "0..*" --> "0..1" Company : 員工/雇主
@enduml
實現: 這人員 表格將有一個外鍵 僱主 參考 公司.
可導航性
使用箭頭指定遍歷方向:

@startuml
class 練習
class 章節
練習 "0..*" --> "1" 章節
@enduml
-
箭頭表示高效遍歷方向
-
在 OODB 中:僅以單向指針實現
-
在 RDBMS 中:無論如何,連接都可雙向運作
具有 的集合類型{有序}

@startuml
class 章節
class 練習
章節 "1" -- "0..*" 練習 : {有序}
@enduml
-
{有序}: 維持順序(使用清單,而非集合) -
在 RDBMS 中的實現:新增順序編號屬性
練習 (
id 主鍵,
chapter_id 參考 章節,
sort_no 整數,
(chapter_id, sort_no) 唯一
)
限定詞
限定詞使用類似鍵的機制來劃分相關物件:

@startuml
class Chapter
class Exercise
Chapter "1" --> "0..1" Exercise : <<qualifier>> no: Integer
@enduml
含義:給定一個章節和練習編號,最多只會返回一個練習。
關聯類
當關聯具有屬性或操作時:
@startuml
class Student
class Exercise
class Solution {
date: Date
points: Integer
}
Student "0..*" -- "0..*" Exercise : has solved
Solution .. Student
Solution .. Exercise
@enduml
-
一個
解答物件對應每對(學生,練習) -
強制執行:同一學生不能為同一練習提交兩個解答
組合與聚合
| 特徵 | 組合(*--) |
聚合(o--) |
|---|---|---|
| 符號 | 黑色菱形 | 白色菱形 |
| 關係 | 整體-部分,強擁有 | 整體-部分,弱引用 |
| 生命週期 | 整體刪除時,零件也一併刪除 | 零件獨立 |
| 多重性 | 整體側為 1 或 0..1 | 任意 |
| RDBMS 映射 | ON DELETE CASCADE |
標準外鍵 |
@startuml
class 章節
class 練習
章節 *-- "0..*" 練習 : 組成
章節 o-- "0..*" 練習 : 聚合
@enduml
🔹 操作與方法
操作宣告語法
@startuml
class 計算器 {
+ getTotal(學號: Integer, 包含額外: Boolean = true): Float {isQuery=true}
+ {static} getInstance(): 計算器
+ {constructor} Calculator(初始值: Float)
- recalculate(): void
}
@enduml
參數規範:
[方向] 名稱: 類型 [= 預設值]
-
方向:
in(預設),out,inout -
預設值可讓參數成為選擇性
特殊操作範疇
| 類型 | 目的 |
|---|---|
{isQuery=true} |
確保不會修改狀態 |
{建構函數} |
建立並初始化新的實例 |
{靜態} |
類別層級操作,無隱含self |
資料庫環境中的操作
文化衝突: 面向物件強調封裝;關聯式強調直接資料存取。
實作策略:
| 操作類型 | RDBMS 實作 |
|---|---|
| 簡單屬性存取 | 直接 SELECT/UPDATE |
| 衍生屬性(無參數) | 資料庫 VIEW |
| 衍生屬性(帶參數) | 儲存程序或應用程式邏輯 |
| 複雜約束強制執行 | 觸發程序或應用程式程序 |
🔹 一般化與繼承
基本一般化
@startuml
class Person
class Student
class Professor
Person <|-- Student
Person <|-- Professor
@enduml
抽象類別與操作
@startuml
抽象類別 Account {
- balance: Float
+ deposit(amount: Float): void
+ {抽象} withdraw(amount: Float): void
}
@enduml
一般化約束
@startuml
class Person
class Student
class Professor
class OtherPerson
Person <|-- Student : <<{互斥, 完整}>>
Person <|-- Professor : <<{互斥, 完整}>>
Person <|-- OtherPerson : <<{互斥, 完整}>>
@enduml
多重分類 / 鑑別器
@startuml
class Employee
class Staff
class Faculty
class HMO
class NonHMO
Employee <|-- Staff : <<類型>>
Employee <|-- Faculty : <<類型>>
Employee <|-- HMO : <<保險>>
Employee <|-- NonHMO : <<保險>>
@enduml
-
鑑別器將互斥的特殊化分組
-
物件在每個鑑別器維度上只能有一個值
🔹 擴展機制
UML 提供三種擴展機制:
1. 標記類型<< >>
透過建立模型元素的新「子類型」來擴展 UML 語義。
@startuml
class Customer <<實體>> {
- id: Integer
- name: String
}
class MathLibrary <<工具>> {
+ sin(x: Float): Float
+ cos(x: Float): Float
}
@enduml
2. 標籤值{鍵=值}
為模型元素新增自訂屬性。
@startuml
class Student {
{author=sb, version=1.0, persistence=persistent}
- id: Integer
}
@enduml
3. 約束{...}
使用自由格式文字、OCL 或預定的縮寫來新增語義限制。
@startuml
class Exercise {
- no: Integer
- points: Integer {value >= 0}
{points <= maxPoints}
}
@enduml
🔹 用於資料庫設計的 UML:關鍵考量
將 UML 轉換為關聯式結構
| UML 結構 | 關聯式實作 |
|---|---|
| 類別 | 資料表 |
| 屬性 | 欄位 |
主要鍵{pk} |
PRIMARY KEY 約束 |
| 關聯 (1:*) | 在「多」端的外來鍵 |
| 關聯 (:) | 連接/交集資料表 |
| 組合 | 外來鍵 +ON DELETE CASCADE |
| 關聯類別 | 具有複合外鍵和屬性的表格 |
| 泛化 | 分離的表格(帶外鍵)或單一表格搭配類型鑑別器 |
{有序}關聯 |
新增序列欄位 + 唯一性約束 |
| 限定詞 | 複合鍵或索引欄位的一部分 |
關鍵差異:物件導向 vs. 關係型
| 面向 | 物件導向 | 關係型 |
|---|---|---|
| 身分識別 | 物件參考(代理) | 主要鍵(業務或代理) |
| 操作 | 設計的核心,封裝的 | 外部(SQL、程序) |
| 封裝 | 私有屬性,公開介面 | 預設直接存取表格 |
| 繼承 | 原生語言支援 | 複雜的對應策略 |
| 關係 | 指標/參考 | 外鍵與連接 |
資料庫設計師的實務建議
-
明確地建模鍵: 使用
{pk},{ak1}型別,因為 UML 缺乏原生金鑰支援 -
標記持久性: 使用
{persistent}標記值,用於區分資料庫類別與暫時性應用程式類別 -
簡化操作: 將查詢操作對應至檢視;複雜操作對應至儲存程序
-
謹慎處理繼承: 根據查詢模式選擇對應策略
-
記錄約束: 使用 OCL 或明確文字約束來表示商業規則
-
審慎使用關聯類別: 僅在關係具有重要屬性時
🎯 快速參考速查表
PlantUML 類別圖符號摘要
@startuml
class <<型別>> 類別名稱 {
{標記=值}
[+/-/#/~] 名稱[多重性]: 類型 [= 值] {屬性}
[+/-/#/~] 名稱(參數): 回傳值 {屬性}
}
@enduml
關聯符號
@startuml
類別A "多重性A" -- "多重性B" 類別B : 關聯名稱
類別A *-- 類別B ' 組合
類別A o-- 類別B ' 聚合
類別A --> 類別B ' 可導航
@enduml
可見性符號
-
+公開 -
-私有 -
#受保護 -
~套件
常見屬性與約束
-
{靜態}/{isQuery=true}/{抽象} -
{值 >= 0}/{互斥}/{有序}/{主鍵}
💡 最終想法: UML類別圖對於概念建模非常強大,但請記住它們主要是為軟體工程設計的。當使用UML進行資料庫設計時,應準備好擴展符號(使用樣式、標籤值、約束),以捕捉關係概念,例如鍵、正規化和宣告式約束,這些都不是UML物件導向基礎的原生功能。
本指南彙整自Stefan Brass所著《第6部分:UML類別圖》,哈雷大學,2003年。所有圖表均以PlantUML語法格式化,以確保與現代工具的相容性。











