UML 類圖(下):關聯、聚合、組合、依賴
前言
上一篇文章 UML 類圖(上):類、繼承、實現,講了 UML 類圖中類、繼承、實現三種關係及其在 UML 類圖中的畫法,本文將接着上文的內容,繼續講講對象之間的其他幾種關係,主要就是關聯、聚合、組合、依賴,下面開始文章的內容。
注意 1:子類中覆蓋了父類的 abstract 方法,方法名再次出現。
注意 2:無論哪種關係,箭頭指向被依賴方。
關聯關係
關聯(Assocition)關係是類與類之間最常見的一種關係,它是一種結構化的關係,表示一類對象與另一類對象之間有聯繫,如汽車和輪胎、師傅和徒弟、班級和學生等。在 UML 類圖中,用實線連接有關聯關係的對象所對應的類,在 Java 中通常將一個類的對象作爲另一個類的成員變量。關聯關係分單向關聯、雙向關聯、自關聯,逐一看一下。
1、單向關聯關係
單向關聯指的是關聯只有一個方向,比如顧客(Customer)擁有地址(Address),其 Java 實現爲:
public class Address
{
}
public class Customer
{
private Address address;
}
UML 的畫法爲:
2、雙向關聯關係
默認情況下的關聯都是雙向的,比如顧客(Customer)購買商品(Product),反之,賣出去的商品總是與某個顧客與之相關聯,這就是雙向關聯。Java 類的寫法爲:
public class Product
{
private Customer customer;
}
public class Customer
{
private Product[] product;
}
對應的 UML 類圖應當是:
3、自關聯關係
自關聯,指的就是對象中的屬性爲對象本身,這在鏈表中非常常見,單向鏈表 Node 中會維護一個它的前驅 Node,雙向鏈表 Node 中會維護一個它的前驅 Node 和一個它的後繼 Node。就以單向鏈表爲例,它的 Java 寫法爲:
public class Node
{
private Node nextNode;
}
對應的 UML 類圖應當是:
聚合關係
聚合(Aggregation)關係表示整體與部分的關係。在聚合關係中,成員對象是整體的一部分,但是成員對象可以脫離整體對象獨立存在。在 UML 中,聚合關係用帶空心菱形的直線表示,如汽車(Car)與引擎(Engine)、輪胎(Wheel)、車燈(Light),Java 表示爲:
public class Engine
{
}
public class Wheel
{
}
public class Light
{
}
public class Car
{
private Engine engine;
private Light light;
private Wheel wheel;
public Car(Engine engine, Light light, Wheel wheel)
{
super();
this.engine = engine;
this.light = light;
this.wheel = wheel;
}
public void drive()
{
}
}
對應的 UML 類圖爲:
代碼實現聚合關係,成員對象通常以構造方法、Setter 方法的方式注入到整體對象之中。
組合關係
組合(Composition)關係也表示的是一種整體和部分的關係,但是在組合關係中整體對象可以控制成員對象的生命週期,一旦整體對象不存在,成員對象也不存在,整體對象和成員對象之間具有同生共死的關係。在 UML 中組合關係用帶實心菱形的直線表示。
比如人的頭(Head)和嘴巴(Mouth)、鼻子(Nose),嘴巴和鼻子是頭的組成部分之一,一旦頭沒了,嘴巴也沒了,因此頭和嘴巴、鼻子是組合關係,Java 表示爲:
public class Mouth
{
}
public class Nose
{
}
public class Head
{
private Mouth mouth;
private Nose nose;
public Head()
{
mouth = new Mouth();
nose = new Nose();
}
public void shake()
{
}
}
其 UML 的表示方法爲:
代碼實現組合關係,通常在整體類的構造方法中直接實例化成員類,這是因爲組合關係的整體和部分是共生關係,如果通過外部注入,那麼即使整體不存在,那麼部分還是存在的,這就相當於變成了一種聚合關係了。
依賴關係
依賴(Dependency)關係是一種使用關係,特定事物的改變有可能會影響到使用該事物的其他事物,在需要表示一個事物使用另一個事物時使用依賴關係,大多數情況下依賴關係體現在某個類的方法使用另一個類的對象作爲參數。在 UML 中,依賴關係用帶箭頭的虛線表示,由依賴的一方指向被依賴的一方。
比如,駕駛員(Driver)開車,Driver 類的 drive() 方法將車(Car)的對象作爲一個參數傳遞,以便在 drive() 方法中能夠調用 car 的 move() 方法,且駕駛員的 drive() 方法依賴車的 move() 方法,因此也可以說 Driver 依賴 Car,Java 代碼爲:
public interface Car
{
public void move();
}
public class Driver
{
public void drive(Car car)
{
car.move();
}
}
其 UML 的畫法爲:
依賴關係通常通過三種方式來實現:
- 將一個類的對象作爲另一個類中方法的參數
- 在一個類的方法中將另一個類的對象作爲其對象的局部變量
- 在一個類的方法中調用另一個類的靜態方法
關聯關係、聚合關係、組合關係之間的區別
從上文可以看出,關聯關係、聚合關係和組合關係三者之間比較相似,本文的最後就來總結一下這三者之間的區別。
關聯和聚合的區別主要在於語義上:關聯的兩個對象之間一般是平等的,聚合則一般是不平等的。
聚合和組合的區別則在語義和實現上都有差別:組合的兩個對象之間生命週期有很大的關聯,被組合的對象在組合對象創建的同時或者創建之後創建,在組合對象銷燬之前銷燬,一般來說被組合對象不能脫離組合對象獨立存在,而且也只能屬於一個組合對象;聚合則不一樣,被聚合的對象可以屬於多個聚合對象。
再舉例子來說:
- 你和你的朋友屬於關聯關係,因爲你和你的朋友之間的關係是平等的,關聯關係只是表示一下兩個對象之間的一種簡單的聯繫而已,就像我有一個朋友
- 你和你借的書屬於聚合關係,第一是因爲書可以獨立存在,第二是因爲書不僅僅屬於你,也可以屬於別人,只是暫時你擁有
- 你和你的心臟屬於組合關係,因爲你的心臟只是屬於你的,不能脫離與你而存在
不過,實際應用中,我個人感覺三種關係其實沒有區分得這麼清楚,有些架構師甚至會說 "組合和聚合沒什麼區別",所以,有時候不需要把細節扣得這麼細,合理利用對象之間的關係給出設計方案即可。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://www.cnblogs.com/liyanwei/p/2c7358fa7b2cd3d75779523cdbb5b31c.html