Java類之間的關聯關系
UML類圖中的關系分為四種:泛化、依賴、關聯、實現;關聯關系又可以細化為聚合和組合。
一、泛化(Generalization)
泛化是父類和子類之間的關系,子類繼承父類的所有結構和行為。在子類中可以增加新的結構和行為,也可以覆寫父類的行為。
一般用一個帶空心箭頭的實線表示泛化關系,UML圖如下:
泛化對應Java中繼承關系,即子類繼承父類中出private修飾外的所有東西(變量、方法等)。示例代碼:
public class Animal {
}
public class Tiger extends Animal {
}
Tiger繼承Animal,因此Tiger與Animal之間是泛化(繼承)關系。這個很好理解。
二、依賴(Dependency)
依賴關系是一種使用關系,特定事物的改變有可能會影響到使用該事物的事物,反之不成立。在你想顯示一個事物使用另一個事物時使用。
一般用一條指向被依賴事物的虛線表示,UML圖如下:
通常情況下,依賴關系體現在某個類的方法使用另一個類作為參數。代碼示例:
public class Screwdriver { //螺絲刀,作為人類的工具,是用來被人類使用的
}
public class Person{
public void screw(Screwdriver src){ //擰螺絲,需使用螺絲刀
}
}
Person類的screw()方法在使用時就得傳入一個Screwdriver類型的參數,這樣Screwdriver的改變就會影響到Person,因此Person與Screwdriver之間就是依賴關系(Person依賴於Screwdriver)。
三、關聯(Association)
是一種結構關系,說明一個事物的對象與另一個事物的對象相聯系。給定有關聯的兩個類, 可以從一個類的對象得到另一個類的對象。關聯有兩元關系和多元關系。兩元關系是指一種一對一的關系,多元關系是一對多或多對一的關系。兩個類之間的簡單關 聯表示了兩個同等地位類之間的結構關系。當你想要表示結構化關系時使用關聯。(可以想想hibernate的關聯關系)
一般用實線連接有關聯的同一個類或不同的兩個類。UML圖如下:
通常情況下,關聯關系是通過類的成員變量來實現的。代碼示例:
public class Company { //公司
private Employee emp ; //一個公司雇員,公司與雇員之間就是一種關聯關系。
}
public class Employee{
}
雇員作為公司的屬性,不同於上面的依賴。依賴的話,雇員的改變會影響公司,顯然不是。在這裡雇員僅僅作為公司的一個屬性而存在。因此Employee與Company之間是關聯關系。關聯關系還可以細分為聚合和組合兩種。
3.1 聚合(Aggregation)
聚合是一種特殊的關聯。它描述了“has a”關系,表示整體對象擁有部分對象。
關聯 關系和聚合關系來語法上是沒辦法區分的,從語義 上才能更好的區分兩者的區別。聚合是較強的關聯關系,強調的是整體與部分 之間的關系。例如,學校和學生 的關系。聚合的整體和部分之間在生命周期上沒有什麼必然的聯系,部分對象可以在整體對象創建之前創建,也可以在整體對象銷毀之後銷毀。
一般用帶一個空心菱形(整體的一端-學校)的實線表示。UML圖如下:
與關聯關系一樣,聚合關系也是通過類的成員變量來實現的。示例代碼:
public class Student{
}
public class School{
private List<Student> students ; //學校與學生是聚合關系
}
學校是整體,而學生是部分。學校與學生都是可以獨立存在的,之間沒有什麼必然的聯系。因此學校與學生就是聚合關系。
3.2 組合(Composition)
組合是聚合的一種形式,它具有更 強的擁有關系,強調整體與部分的生命周期是一致的,整體負責部分的生命周期的管理。生命周期一致指的是部分必須在組合創建的同時或者之後創建,在組合銷毀 之前或者同時銷毀,部分的生命周期不會超出組合的生命周期。例如Windows的窗口和窗口上的菜單就是組合關系。如果整體被銷毀,部分也必須跟著一起被 銷毀,如果所有者被復制,部分也必須一起被復制。
一般用帶實心菱形(整體的一端)的實線來表示。UML圖如下:
與關聯關系一樣,組合關系也是通過類的成員變量 來實現的。示例代碼:
public class Menu{
}
public class Window{
private List<Menu> menus ;
}
菜單的存在前提是窗口的存在,兩者之間存在很強的擁有關系。且窗口對菜單的生命周期負責,只有在窗口創建之後,菜單才能夠創建,菜單必須在窗口銷毀之前銷毀。因此Window與Menu之間是組合關系。
聚合和組合的區別在於:
聚合 關系是“has-a”關系,組合關系是“contains-a”關系;聚合關系表示整體與部分的關系比較弱,而組合比較強;聚合關系中代表部分事物的對象 與代表聚合事物的對象的生存期無關,一旦刪除了聚合對象不一定就刪除了代表部分事物的對象。組合中一旦刪除了組合對象,同時也就刪除了代表部分事物的對 象。
另外有一個差別是組合中的一個對象在同一時刻只能屬於一個組合對象,而聚合的一個部分對象可以被多個整體對象聚合,例如一個學生可以在多個學校就讀,而一個菜單在同一時刻只能是某個窗口內的對象。
四、實現(Realization)
實現關系指定兩個實體之間的一個合約。換言之,一個實體定義一個合約,而另一個實體保證履行該合約。對類來說,就是一個類實現了一個接口。
一般用一條指向接口的虛線表示,UML圖如下:
實現對應Java中的實現接口(implements)。示例代碼:
public interface Person{
}
public class Student implements Person{
}
這個和泛化一樣很好理解。
五、總結
類間關系有很多種,在大的類別上可以分為兩種:縱向關系、橫向關系。縱向關系就是繼承關系,它的概念非常明確,也成為OO的三個重要特征之一,這裡不過多的討論。
橫向關系較為微妙,按照UML的建議大體上可以分為四種:
依賴 (Dependency)
關聯 (Association)
聚合 (Aggregation)
組合 (Composition)
關於關聯,聚合,組合在實現上並沒有顯著區別,相區別他們只有通過判斷關系雙方之間的實際關系,如關系強弱、創建與銷毀之間有無必要關聯等。
它們的強弱關系是沒有異議的:依賴 < 關聯 < 聚合 < 組合<泛化(繼承)
實現方式區別:
(1) 依賴關系:關系對象出現在局部變量或者方法的參數裡,或者關系類的靜態方法被調用
(2) 關聯關系:關系對象出現在實例變量中
(3) 聚合關系:關系對象出現在實例變量中
(4) 合成關系:關系對象出現在實例變量中
(5) Generalization: extends
(6) 實現: implements