1. 程式人生 > >Java類之間的關聯關係

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