關聯是一種結構關系,說明一個事物的對象與另一個事物的對象相聯系。給定一個連接兩各類的關聯,可以從一個類的對象導航到另一個類的對象。
一般把關聯畫為連接相同或者不同的類一條實線。關聯可以有方向,即導航。一般不作說明的時候,導航是雙向的,不需要在線上標出箭頭。大部分情況下導航是單向的,可以加一個箭頭表示。
關聯在代碼中一般表示為屬性,例如
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
?
聚合是這樣的:學生與所選課程之間的關系就是組合,他們之間在感念上沒有必然關系,刪掉一門課程,不會影響到學生
組合是這樣的:訂單和訂單條目的關系就是聚合,他們的關系很緊密,刪掉一個訂單,訂單條目也就沒有意義了
組合是聚合的一種形式