[摘自 Java開發人員 frenzied]
關係是事物之間的聯絡。類之間有4種重要的關係:依賴、泛化、關聯和實現。這些關係都可以映射到代碼裡。
依賴是一種使用關係,描述了一個事物的規格說明的變化可能會影響到使用它的另一個事物(反之不一定)。在UML中表示為一條指向被依賴事物的虛線。依賴有很多構造型,不過一般不需要使用,以免搞得過份複雜。其實另外3種關係泛化、關聯和實現都可以算作是某種依賴關係,只不過它們有比較強的語義和重要的作用,所以劃分出來。一般對類別關係建模的時候,先對泛化、關聯和實現建模,剩下的關係都可以看作依賴了。
對應到代碼中,依賴關係可能有很多種形式,例如
public class A
{
public B getB(C c, D d)
{
E e = new E();
B b = new B(c, d, e);
}
}
這裡類A就依賴於類B(方法返回類)、C和D(參數類)、E(方法內變數的類),因為這幾個類的變化都有可能影響到類A
泛化是一般事物(稱為超類或父類)和較特殊的事務(稱為子類)之間的關係,對類來說一般就是繼承了,如:public Class A extends B。一般用一個帶空心箭頭的實線表示泛化關係。
關聯是一種結構關係,說明一個事物的對象與另一個事物的對象相聯絡。給定一個串連兩各類的關聯,可以從一個類的對象導航到另一個類的對象。
一般把關聯畫為串連相同或者不同的類一條實線。關聯可以有方向,即導航。一般不作說明的時候,導航是雙向的,不需要線上上標出箭頭。大部分情況下導航是單向的,可以加一個箭頭表示。
關聯在代碼中一般表示為屬性,例如
public class A
{
private B b;
}
可以認為有一個A指向B的關聯。
如果B也關聯到A,那麼它們就是雙向的關聯。
有的時候B不是A的屬性,但是也可以有關聯關係,例如:
public class A
{
public B[] getBs()
{...}
}
方法getBs可能去查資料庫,找到A和B之間的關聯關係。
兩個類之間的簡單關聯表示了兩個同等地位類之間的結構關係。彙總也是一種關聯關係,與簡單關聯不同的是,它描述的是一個整體和組成部分的關係,即“has-a”關係,意思是整體對象擁有部分對象,例如學校和學生的關係。彙總的整體和部分之間在生命週期上沒有什麼必然的聯絡,部分對象可以在整體對象建立之前建立,也可以在整體對象銷毀之後銷毀。彙總用帶一個空心菱形(整體的一端)的實線表示。
public Class Person
{...}
public Class School
{
private ArrayList students;
private void addStudent(Person person)
{
students.add(person);
}
}
組合則是比彙總更強的關聯形式。組合是指帶有很強的擁有有關係且整體與部分的生命週期一致的彙總關聯形式。例如Windows的視窗和視窗上的菜單就是組合關係。生命週期一致指的是部分必須在組合建立的同時或者之後建立,在組合銷毀之前或者同時銷毀,部分的生命週期不會超
出組合的生命週期。組合是用帶實心菱形的實線來表示。
public Class Menu
{...}
public Class Window
{
private Menu menu;
}
組合和彙總在代碼實現上的主要差別在於生命週期的實現上,組成需要負責其部分的建立和銷毀。
public Class School
{
public School()
{...}//不需要建立任何Person對象,其Students都是已有的Person對象
public void destroy()
{...}//只需要關掉School對象和斷開它與自己所有的Person對象的關聯即可,Person對象是不會銷毀的
}
public Class Window
{
private Menu menu;
public Window()
{
menu = new Menu();
}//可以在這時候建立Menu對象,也可以在之後建立
public void destory()
{
menu.destory();
}//必須同時或者在這之前銷毀關聯的Menu對象
}
另外有一個差別是組合中的一個對象在同一時刻只能屬於一個組成對象,而彙總的一個部分對象可以被多個整體對象彙總,例如一個學生可以在多個學校就讀,而一個菜單在同一時刻只能是某個視窗內的對象。
實現關係就比較簡單了,指的是一個類元描述了另一個類元保證實現的契約。對類來說,就是一個類實現了一個介面
public interface A
{
public void methodA();
}
public class B implements A
{
public void methodA()
{...}
...
}
一般在面對對象的系統中,儘可能的使用介面來減少類之間的耦合。因為介面沒有實現,所以依賴於介面就不會依賴於某種具體實現,例如jdbc裡的Connection和ResultSet都是介面,不同資料庫廠商的實現可以不一樣。
總結一下
1)依賴關係:關聯性物件出現在局部變數或者方法的參數裡,或者關係類的靜態方法被調用
2)關聯關係:關聯性物件出現在執行個體變數中
3)彙總關係:關聯性物件出現在執行個體變數中
4)合成關係:關聯性物件出現在執行個體變數中
5)Generalization: extends
6)實現: implements
彙總是這樣的:學生與所選課程之間的關係就是組合,他們之間在感念上沒有必然關係,刪掉一門課程,不會影響到學生
組合是這樣的:訂單和訂單條目的關係就是彙總,他們的關係很緊密,刪掉一個訂單,訂單條目也就沒有意義了
組合是彙總的一種形式