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

Java 中聚合與組合的區別與聯繫:從「Has-a」關係到 UML 圖解

     編輯:Java 綜合教學

前言:物件導向設計中的「整體-部分」關係

在 Java 物件導向設計中,「聚合」與「組合」是描述類之間「擁有」關係的兩核心概念。它們皆屬於關聯關係的一種特殊形式,均表達「Has-a」(有一個)的語義,但在生命週期綁定強度、所有權獨佔性上存在本質差異。本文將結合《Java 語言程式設計(第 8 版)》經典案例,從定義、代碼表現、UML 表示、生命週期管理四個維度深度解析兩者區別與聯繫。

一、核心定義對比

1. 聚合 —— 弱「擁有」關係

聚合模擬「Has-a」關係,表示兩個對象之間的歸屬關係。所有者對象(聚合對象)與被擁有對象(被聚合對象)擁有獨立生命週期。關鍵特徵:

  • 共享性:一個被聚合對象可被多個聚合對象同時擁有(如:多個學生共享同一地址對象)
  • 獨立性:聚合對象銷毀時,被聚合對象不會被銷毀
  • 代碼表現:通常表現為聚合類中的一個引用類型數據域(成員變量)

2. 組合 —— 強「擁有」關係

組合是聚合的特殊形式,代表「Contains-a」關係。整體對象獨佔擁有部分對象,生命週期完全綁定。關鍵特徵:

  • 獨佔性:一個部分對象只能歸屬於一個整體對象(如:學生與姓名,姓名不可被其他學生共享)
  • 同生共死:整體對象創建時創建部分,銷毀時銷毀部分
  • 代碼表現:通常在構造函數中直接實例化部分對象,或通過工廠方法創建

二、經典案例解析:學生、姓名與地址

教材中的經典例子最能直觀說明差異:

  • 「一個學生有一個姓名」→ 組合:姓名對象專屬於該學生,學生對象銷毀時姓名對象也應銷毀,不可共享
  • 「一個學生有一個地址」→ 聚合:地址對象可被多個學生共享(如同宿舍學生),學生畢業離校時地址對象仍存在

三、UML 類圖表示規範

統一建模語言(UML)使用菱形標識區分兩者:

  • 實心菱形(◆)+ 實線:組合關係,菱形指向整體類
  • 空心菱形(◇)+ 實線:聚合關係,菱形指向聚合類

UML 聚合與組合圖示

四、代碼層面的實現差異

聚合關係代碼示例

public class Student {
    private Address address; // 引用外部傳入的地址對象
    
    public Student(Address address) {
        this.address = address; // 不負責創建 Address
    }
}
// 使用場景:同一 Address 實例可傳給多個 Student
Address sharedAddr = new Address("北京市海淀區");
Student s1 = new Student(sharedAddr);
Student s2 = new Student(sharedAddr); // 共享同一地址對象

組合關係代碼示例

public class Student {
    private final Name name; // 獨佔擁有,final 保證不可變更引用
    
    public Student(String nameStr) {
        this.name = new Name(nameStr); // 內部直接創建,生命週期綁定
    }
}
// Name 類通常設計為不可變類,無 setter 方法

五、同一類內部的聚合關係

聚合關係還可存在於同一類的對象之間。例如「員工-管理者」關係:

  • 一個員工有一個管理者(單一引用)
  • 一個管理者可管理多個員工(一對多)
  • 代碼中可用單一引用或數組/集合表示

自聚合關係示例

六、設計選擇指南:何時用聚合?何時用組合?

判斷標準選擇組合選擇聚合
部分對象是否可被多個整體共享?否(獨佔)是(共享)
整體銷毀時部分是否必須銷毀?是(同生共死)否(獨立存活)
部分對象是否有獨立業務意義?無(僅作為整體一部分存在)有(可獨立被其他業務引用)
典型場景訂單-訂單項、房子-房間、大學-學院學生-地址、教師-課程、用戶-角色

七、總結

聚合與組合本質上都是「Has-a」關係的具體化,核心差異在於所有權強度與生命週期綁定。掌握二者區別對於領域模型設計、資料庫關係映射(如 JPA @OneToMany vs @Embedded)、系統解耦至關重要。實際開發中,寧可優先考慮聚合(鬆耦合),只有在明確需要強生命週期綁定、獨佔擁有語義時才使用組合。

記住:UML 中實心菱形=組合(強),空心菱形=聚合(弱)。代碼中組合通常在構造器中 new 部分對象,聚合通常通過構造器/Setter 注入外部對象。

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