開始一個新的軟體專案時,最重要的步驟通常發生在撰寫任何程式碼之前。這一步驟涉及使用視覺模型來規劃應用程式的結構。在統一模型語言(UML)提供的各種圖表中,類圖是物件導向設計的骨幹。它作為藍圖,顯示系統的靜態結構。了解類圖的各個元件,對於任何希望建立可擴展且易於維護系統的開發人員來說都至關重要。
本指南詳細介紹類圖中的每一項元件。我們將探討如何定義類別、管理關係以及應用可見性規則。透過掌握這些概念,您能確保程式碼反映出團隊容易遵循的邏輯架構。

什麼是類圖? 🏗️
類圖是一種靜態結構圖,透過顯示系統的類別、屬性、操作(或方法)以及物件之間的關係,來描述系統的結構。與顯示時間上行為的序列圖不同,類圖專注於靜態結構。
- 靜態結構: 它代表系統在某一特定時刻的狀態。
- 物件導向: 它符合大多數現代語言(如 Java、C++ 和 Python)組織資料的方式。
- 文件化: 它作為開發人員與利益相關者之間的契約。
把它想像成一棟房子的建築平面圖。你不需要看到水管或電線佈置,就能理解房間和牆壁的結構。同樣地,類圖顯示「房間」(類別)以及它們之間的連接方式,而不需詳細說明每個函式內部的具體邏輯。
類框的核心元件 📦
類圖的核心是類框。這個矩形代表系統中的單一類別。它通常被分為三個部分。
1. 類別名稱(頂端部分) 🏷️
頂端部分存放類別的名稱。命名慣例在此至關重要。請使用駝峰式命名法來命名類別(例如,UserAccount, PaymentProcessor)。這能讓類別與屬性和方法區分開來。
- 大小寫: 永遠以大寫字母開頭。
- 唯一性: 確保名稱在套件或命名空間內是唯一的。
- 以名詞為基礎: 類別通常應代表名詞(例如,Customer、Order),而非動詞。
2. 屬性(中間部分) 📝
中間部分列出類別的屬性或特性。屬性代表此類別物件所持有的狀態或資料。
每個屬性通常遵循此格式:
可見性 名稱 : 類型 = 初始值
- 可見性: 定義誰可以存取該屬性(請參閱可見性修飾符部分)。
- 名稱: 程式碼中使用的變數名稱。
- 類型: 資料類型(例如,字串、整數、布林值)。
- 初始值: 建立時可選的預設值。
範例: - 帳戶餘額 : 双精度浮點數 = 0.00
3. 操作/方法(底部區塊) ⚙️
底部區塊列出操作或方法。這些是類別可以執行的行為。
格式通常如下所示:
可見性 操作名稱 (參數) : 回傳類型
- 操作名稱: 描述動作的動詞(例如,
計算總額,登入). - 參數:執行方法所需的輸入值。
- 回傳類型: 執行後回傳的資料類型。
範例: + 存款(金額 : 双精度浮點數) : 無值
可見性修飾符 🔒
可見性決定屬性和方法從其他類別的存取權限。這是封裝的一個關鍵概念。圖表中使用四種標準符號。
- 公開 (+): 可從任何類別存取。這是存取權限最開放的層級。
- 私有 (-): 僅可在類別內部存取。這在許多語言中是預設值,對於內部資料最為安全。
- 保護 (#): 可在類別及其子類別(子類)中存取。這支援繼承機制。
- 套件 (~): 僅可在同一套件或命名空間內存取。這通常用於內部工具類別。
使用正確的可見性修飾符可防止意外的副作用。如果你將私有屬性公開為公開,程式碼的其他部分可以直接修改它,從而繞過驗證邏輯。
理解關係 🔗
類別很少孤立存在。它們彼此互動,形成一個完整的系統。這些互動以連接類別的線條來表示,稱為關係。理解這些線條之間的差異對於準確建模至關重要。
1. 關聯 🔗
關聯表示一種結構關係,其中一個類別的物件與另一個類別的物件相連結。這是連結的一般性術語。
- 實線: 用於繪製標準關聯。
- 方向: 箭頭表示導航性(誰知道誰)。
- 範例: 一位
教師教導一位學生.
2. 聚合 🟢
聚合是關聯的一種特殊形式,表示「整體-部分」關係,其中部分可以獨立於整體存在。
- 空心菱形: 放置在線條的「整體」一側。
- 獨立性: 如果整體被銷毀,部分仍然存在。
- 範例: 一個
部門擁有員工。如果部門關閉,員工仍可能在其他地方存在。
3. 組成關係 🟦
組成關係是聚合的一種更強形式。它暗示零件無法在沒有整體的情況下存在。
- 實心菱形: 放置在線的「整體」一側。
- 依賴: 如果整體被摧毀,零件也會隨之被摧毀。
- 範例: 一個
房屋擁有房間。如果房屋被拆除,這些房間就不再作為該房屋的一部分存在。
4. 一般化(繼承) 📉
一般化代表一種「是」關係。子類別會從超類別繼承屬性和操作。
- 空心三角箭頭: 箭頭從子類別指向超類別。
- 可重用性: 允許程式碼重用與多型性。
- 範例: 一個
汽車是一種車輛。一個轎車是一個汽車.
5. 依賴關係 🔄
依賴關係表示一個類別僅暫時使用或依賴另一個類別。這通常是一種「使用一個」的關係。
- 虛線箭頭:從依賴的類別指向被使用的類別。
- 暫時性: 這種關係通常是短暫的(例如,方法參數)。
- 範例: 一個
報表產生器使用一個資料庫連接來取得資料,但不會永久持有對它的參考。
為釐清這些關係,請參考下方的比較表格。
| 關係類型 | 符號 | 含義 | 部分的生存週期 |
|---|---|---|---|
| 關聯 | 實線 | 結構性連結 | 獨立 |
| 聚合 | 空心菱形 | 整體-部分(弱) | 獨立 |
| 組合 | 實心菱形 | 整體-部分(強) | 依賴 |
| 繼承 | 三角箭頭 | 是-一種關係 | 不適用 |
| 依賴 | 虛線箭頭 | 使用-一種關係 | 暫時 |
多重性和基數 📐
多重性定義了一個類別的實例與另一個類別的實例之間的數量關係。這通常以範圍形式寫在關係線的末端附近。
- 1:恰好一個。
- 0..1:零個或一個(可選)。
- 1..*:一個或多個(必要)。
- 0..*:零個或多個(可選集合)。
- n:一個特定的數字。
範例情境:考慮一個圖書館以及一個書.
- 圖書館必須至少有一本書(
1..*). - 一本書僅屬於一個圖書館(
1).
正確定義多重性可防止邏輯錯誤。例如,如果你將關係建模為 0..1,但你的程式碼要求至少有一個,你將遇到空參考錯誤。
介面與抽象類別 🧩
並非所有類別都旨在被實例化。有些僅作為範本或合約使用。
抽象類別
抽象類別無法直接實例化。它為子類別提供基礎實作。在圖表中,類別名稱通常以斜體或以關鍵字{abstract}.
- 用於一組類別之間的共用行為。
- 可同時包含抽象方法(無主體)與具體方法(有主體)。
介面
介面定義了一組類別必須實作的方法。它不儲存狀態(屬性)。
- 用於在無關聯的類別之間定義合約。
- 在圖表中,通常以帶有關鍵字的類別方框表示
{interface}或一個綱要圖示。 - 使多型成為可能,讓不同類別可被統一處理。
理解這兩者的差異至關重要。當你需要在不同類型之間共享共同行為時,使用介面;當你需要共享程式碼與狀態時,使用抽象類別。
初學者最佳實務 🎓
建立類別圖表需要紀律。以下是一些指南,以確保你的圖表保持實用且準確。
- 保持簡單: 不要試圖在一個圖表中建模整個系統。應將其分解為子系統或套件。
- 專注於重要元素: 不要包含每一種方法。僅包含定義類別行為的最重要方法。
- 命名一致: 堅持嚴格的命名規範。如果你使用
camelCase來命名屬性,就應在所有地方都使用它。 - 定期審查: 隨著程式碼的演進,圖示也應同步更新。一份過時的圖示,甚至比沒有圖示更糟糕。
- 智慧地使用工具: 使用圖示軟體來維持一致性,但請確保邏輯來自你的思考,而非工具本身。
應避免的常見錯誤 🚫
即使經驗豐富的開發人員在建模時也會犯錯。了解常見陷阱,能幫助你在重構時節省時間。
- 混淆聚合與組合: 這兩者經常被混淆。請記住:如果部分隨著整體消亡,則為組合;如果部分能獨立存活,則為聚合。
- 過度設計: 不要建立過深的繼承層級(祖父 → 父親 → 兒子 → 子孫)。這會使程式碼僵化且難以修改。
- 忽略多重性: 忘記定義有多少物件被連結,可能會導致程式碼實作上的模糊。
- 循環依賴: 避免出現類別 A 依賴類別 B,而類別 B 又依賴類別 A 的情況。這會形成一個循環,使初始化變得複雜。
從圖示到程式碼 💻
最後一步是將視覺模型轉換為實際的原始碼。這個過程通常稱為「正向工程」。
- 產生程式碼: 許多工具能從類別圖產生骨架程式碼。
- 逆向工程: 你也可以從現有的程式碼產生圖示,以記錄遺留系統。
- 手動對應: 有時,手動對應更佳。你可能需要重構圖示,以符合你所使用的語言特性。
確保程式碼中的可見性修飾符與圖示中的符號一致。圖示中的私有屬性在程式碼中也必須是私有的。這種對齊能確保資料完整性。
結論:建立堅實的基礎 🚀
建立類別圖不僅僅是畫方框和線條。這是一種思考過程,迫使你在建構軟體之前就定義其結構。透過理解本指南中所列的元件、關係與規則,你為專案建立了穩固的基礎。
從小處著手。先建立一個簡單的類別,加入屬性,加入方法,再與另一個類別連接。逐步增加複雜度。這種迭代方式能讓你在不感到壓力的情況下,學習物件導向設計的細節。
請記住,目標是清晰。一份優秀的類別圖能清楚地向其他開發人員傳達意圖。它能減少模糊性,為穩健且可維護的程式碼奠定基礎。花點時間,遵循標準,你會發現自己的編碼過程變得更有條理且更有效率。











