UML中類之間的幾種關係,關聯(association),聚合(Aggregation),組合(Composition)
阿新 • • 發佈:2019-01-04
類之間可能存在以下幾種關係:關聯(association)、依賴(dependency)、聚合(Aggregation,也有的稱聚集)、組合(Composition)、泛化(generalization,也有的稱繼承)、實現(Realization)。
關聯是指兩個類之間存在某種特定的對應關係,例如客戶和訂單,一個訂單隻能屬於某個客戶,一個客戶可能會有多張訂單。根據方向,分為單向和雙向。根據對應的數量分為一對一、一對多、多對多等。對應的UML圖如下所示:
關聯關係用實線+箭頭表示。上圖顯示Customer和Order是雙向一對多關聯關係。對應的Java程式碼如下所示:
依賴關係用虛線+箭頭表示。上圖顯示Bicycle和Pump是依賴關係,Bicycle依賴於Pump。對應的Java程式碼如下所示:
聚合使用空心菱形+實線表示。上圖顯示Computer是由MainBoard和DisplayCard等組成的。對應的Java程式碼如下所示:
泛化用空心三角形+實線表示。上圖表示Student繼承People。對應的Java程式碼如下所示:
實現用三角形箭頭和虛線表示。上圖表示類CarDriver和PlaneDriver都實現了Driver介面。對應的Java程式碼如下所示:
關聯關係用實線+箭頭表示。上圖顯示Customer和Order是雙向一對多關聯關係。對應的Java程式碼如下所示:
class Customer { private Integer id; private String name;
private Set<Order> orders;
public Set<Order> getOrders() { return orders; }
public void setOrders(Set<Order> orders) { this.orders = orders; }
}
class Order { private Integer id; private float money;
private Customer customer;
public Customer getCustomer() { return customer; }
public void setCustomer(Customer customer) { this.customer = customer; }
}Customer和Order是雙向一對多關聯關係,那麼在Customer中應該有Order的集合,在Order中應該Customer的屬性。 依賴指的是類之間的呼叫關係。類A訪問類B的屬性或方法,或者類A負責例項化類B,那麼就說類A依賴於類B。和關聯關係不同的是,無需在類A中定義類B型別的屬性。例如自行車和打氣筒,自行車通過打氣筒來充氣,那麼就需要呼叫打氣筒的充氣方法。對應的UML圖如下所示:
依賴關係用虛線+箭頭表示。上圖顯示Bicycle和Pump是依賴關係,Bicycle依賴於Pump。對應的Java程式碼如下所示:
class Bicycle { public void expand(Pump pump) { pump.blow(); } }
class Pump { public void blow() { System.out.println("正在充氣......"); } }打氣筒並不屬於某個特定的自行車,一個打氣筒可以為多個自行車提供充氣的服務。在Bicycle中不需要定義Pump型別的屬性,而是將傳遞了一個Pump型別的引數到Bicycle的方法中。 聚合是整體與部分之間的關係。例如計算機和主機板,計算機是一個整體,主機板是其中的一部分,主機板、顯示卡、顯示器等部件組成了計算機。對應的UML圖如下所示:
聚合使用空心菱形+實線表示。上圖顯示Computer是由MainBoard和DisplayCard等組成的。對應的Java程式碼如下所示:
class Computer { private MainBoard mainBoard; private DisplayCard displayCard; public void on() { System.out.println("開啟計算機......"); }
public void close() { System.out.println("關閉計算機......"); }
public void run() { System.out.println("計算機正在執行......"); } }
class MainBoard { public void control() { System.out.println("控制計算機......"); } }
class DisplayCard { public void display() { System.out.println("計算顯示資料......"); } }計算機由主機板、顯示卡等部件組成,所以在Computer中定義了MainBoard和DisplayCard型別的屬性。 聚合中類之間可以獨立出來,比如一塊主機板可以狀態A計算機上,也可以裝在B計算機上。也就是說這塊主機板離開A計算機之後仍然是有意義的。 組合中的類也是整體與部分的關係,與聚合不同的而是,其中的類不能對立出來。例如一個人由頭、手、腿和軀幹等組成,如果這個頭離開了這個人,那麼這個頭就沒有任何意義了。對應的UML圖如下所示: 組合使用實心菱形和實線表示。上圖表示People是由Head、Hand、Leg等組成。對應的Java程式碼如下所示:
class People { private Head head; private Hand hand; private Leg leg;
public void think() { head.think(); }
public void holdThing() { hand.holdThing(); }
public void walk() { leg.walk(); } }
class Head { public void think() { System.out.println("思考......"); } }
class Hand { public void holdThing() { System.out.println("拿東西......"); } }
class Leg { public void walk() { System.out.println("走路......"); } }People和Head、Hand、Leg是不可分割的,Head、Hand、Leg離開了People沒有任何實際意義。在People中定義了Head、Hand、Leg型別的屬性,組合也可以看成是聚合的一種特殊形式。 聚合和組合的程式碼幾乎相同,單憑程式碼是無法區分兩個類之間是聚合還是組合的關係的。所以就需要結合實際的業務環境來區分。例如汽車和輪胎,車主買了一輛汽車,上邊肯定是由輪胎的,在這個業務中,輪胎和汽車是組合關係,它們分開就沒有實際意義了。在汽車修理店,汽車可以更換輪胎,所以在汽修店的業務環境中,汽車和輪胎就是聚合的關係,輪胎離開汽車是有業務意義的。 泛化比較好理解,就是兩個類之間具有繼承關係。例如人和學生,學生繼承了人,除過具有人的一般的屬性和方法之外,他還要有學習的方法。對應的UML圖如下所示:
泛化用空心三角形+實線表示。上圖表示Student繼承People。對應的Java程式碼如下所示:
class People { protected String name; protected String sex; protected Date birthday;
public void eat() { System.out.println(name + "正在吃飯......"); }
public void drink() { System.out.println(name + "正在喝水......"); }
public void sleep() { System.out.println(name + "正在休息......"); } }
class Student extends People { public void study() { System.out.println(name + "正在學習......"); } }Student繼承自People,並且多了一個study的方法。 實現即一個類實現了某個介面。對應的UML圖如下所示:
實現用三角形箭頭和虛線表示。上圖表示類CarDriver和PlaneDriver都實現了Driver介面。對應的Java程式碼如下所示:
public interface Driver { void drive(); } class CarDriver implements Driver {
public void drive() { System.out.println("駕駛汽車......"); }
}
class PlaneDriver implements Driver {
public void drive() { System.out.println("駕駛飛機......"); }
}值得注意的是,關聯、依賴、聚合、組合的關係很容易搞混。當物件A和物件B之間存在關聯、依賴、聚合或者組合關係時,物件A都有可能呼叫物件B的方法。這是它們的相同之處。另外它們還有自己的特徵。 對於兩個相對獨立的物件A和B,當一個物件A的例項與B的例項存在固定的對應關係時,這兩個物件之間為關聯關係。程式碼中表現為在A中定義了B型別的屬性。 對於兩個相對獨立的物件A和B,當一個物件A負責構造物件B的例項,或者呼叫物件B提供的服務時,這兩個物件之間主要體現為依賴關係。程式碼中的表現即將B型別的引數傳入A的方法中,而不是在A中定義B型別的屬性。 聚合、組合與關聯在程式碼中並沒有明顯的區別,主要看實際的業務環境,根據程式碼所處的實際業務環境來判斷它們之間的關係。同樣的兩個類,處在不同的業務環境中,可能它們的關係也不相同。