UML的類圖關系分為: 關聯、聚合/組合、依賴、泛化(繼承)


UML的類圖關系分為: 關聯、聚合/組合、依賴、泛化(繼承)。而其中關聯又分為雙向關聯、單向關聯、自身關聯;下面就讓我們一起來看看這些關系究竟是什么,以及它們的區別在哪里。

1、關聯


雙向關聯:
C1-C2:指雙方都知道對方的存在,都可以調用對方的公共屬性和方法。

在GOF的設計模式書上是這樣描述的:雖然在分析階段這種關系是適用的,但我們覺得它對於描述設計模式內的類關系來說顯得太抽象了,因為在設計階段關聯關系必須被映射為對象引用或指針。對象引用本身就是有向的,更適合表達我們所討論的那種關系。所以這種關系在設計的時候比較少用到,關聯一般都是有向的。

使用ROSE 生成的代碼是這樣的: 

class  C1    
... {
public :
    C2
*  theC 2;


}
;

class C2 
...{
public:
    C1
* theC1;

}
;

雙向關聯在代碼的表現為雙方都擁有對方的一個指針,當然也可以是引用或者是值。




單向關聯:
C3->C4:表示相識關系,指C3知道C4,C3可以調用C4的公共屬性和方法。沒有生命期的依賴。一般是表示為一種引用。

生成代碼如下:

class C3 
...{
public:
    C4
* theC4;

}
;

class C4 
...{

}
;

單向關聯的代碼就表現為C3有C4的指針,而C4對C3一無所知。





自身關聯(反身關聯):
自己引用自己,帶着一個自己的引用。

代碼如下:

class C14 
...{
public:
    C14
* theC14;

}
;

就是在自己的內部有着一個自身的引用。

2、聚合/組合

當類之間有整體-部分關系的時候,我們就可以使用組合或者聚合。




聚合:表示C9聚合C10,但是C10可以離開C9而獨立存在(獨立存在的意思是在某個應用的問題域中這個類的存在有意義。這句話怎么解,請看下面組合里的解釋)。

代碼如下:

class C9 
...{
public:
    C10 theC10;

}
;

class C10 
...{

}
;





組合(也有人稱為包容):一般是實心菱形加實線箭頭表示,如上圖所示,表示的是C8被C7包容,而且C8不能離開C7而獨立存在。但這是視問題域而定的,例如在關心汽車的領域里,輪胎是一定要組合在汽車類中的,因為它離開了汽車就沒有意義了。但是在賣輪胎的店鋪業務里,就算輪胎離開了汽車,它也是有意義的,這就可以用聚合了。在《敏捷開發》中還說到,A組合B,則A需要知道B的生存周期,即可能A負責生成或者釋放B,或者A通過某種途徑知道B的生成和釋放。

他們的代碼如下:

class C7 
...{
public:
    C8 theC8;

}
;

class C8 
...{
}
;

可以看到,代碼和聚合是一樣的。具體如何區別,可能就只能用語義來區分了。

3、依賴




依賴:
C5可能要用到C6的一些方法,也可以這樣說,要完成C5里的所有功能,一定要有C6的方法協助才行。C5依賴於C6的定義,一般是在C5類的頭文件中包含了C6的頭文件。ROSE對依賴關系不產生屬性。

注意,要避免雙向依賴。一般來說,不應該存在雙向依賴。

ROSE生成的代碼如下:


// C5.h
#include "C6.h"

class C5 
...{

}
;

// C6.h
#include "C5.h"

class C6
...{

}
;


雖然ROSE不生成屬性,但在形式上一般是A中的某個方法把B的對象作為參數使用(假設A依賴於B)。如下:
#include "B.h"
class A
...{
          
void Func(B &b);
}


那依賴和聚合/組合、關聯等有什么不同呢?

關聯是類之間的一種關系,例如老師教學生,老公和老婆,水壺裝水等就是一種關系。這種關系是非常明顯的,在問題領域中通過分析直接就能得出。

依賴是一種弱關聯,只要一個類用到另一個類,但是和另一個類的關系不是太明顯的時候(可以說是“uses”了那個類),就可以把這種關系看成是依賴,依賴也可說是一種偶然的關系,而不是必然的關系,就是“我在某個方法中偶然用到了它,但在現實中我和它並沒多大關系”。例如我和錘子,我和錘子本來是沒關系的,但在有一次要釘釘子的時候,我用到了它,這就是一種依賴,依賴錘子完成釘釘子這件事情。

組合是一種整體-部分的關系,在問題域中這種關系很明顯,直接分析就可以得出的。例如輪胎是車的一部分,樹葉是樹的一部分,手腳是身體的一部分這種的關系,非常明顯的整體-部分關系。

上述的幾種關系(關聯、聚合/組合、依賴)在代碼中可能以指針、引用、值等的方式在另一個類中出現,不拘於形式,但在邏輯上他們就有以上的區別。

這里還要說明一下,所謂的這些關系只是在某個問題域才有效,離開了這個問題域,可能這些關系就不成立了,例如可能在某個問題域中,我是一個木匠,需要拿着錘子去干活,可能整個問題的描述就是我拿着錘子怎么釘桌子,釘椅子,釘櫃子;既然整個問題就是描述這個,我和錘子就不僅是偶然的依賴關系了,我和錘子的關系變得非常的緊密,可能就上升為組合關系(讓我突然想起武俠小說的劍不離身,劍亡人亡...)。這個例子可能有點荒謬,但也是為了說明一個道理,就是關系和類一樣,它們都是在一個問題領域中才成立的,離開了這個問題域,他們可能就不復存在了。


4、泛化(繼承)




泛化關系:如果兩個類存在泛化的關系時就使用,例如父和子,動物和老虎,植物和花等。
ROSE生成的代碼很簡單,如下:

#include "C11.h"

class C12 : public C11
...{
}
;


5、這里順便提一下模板



上面的圖對應的代碼如下:
template<int>
class C13 
...{
}
;


這里再說一下重復度,其實看完了上面的描述之后,我們應該清楚了各個關系間的關系以及具體對應到代碼是怎么樣的,所謂的重復度,也只不過是上面的擴展,例如A和B有着“1對多”的重復度,那在A中就有一個列表,保存着B對象的N個引用,就是這樣而已。

  我的理解是:當我們在一個類中,需要聲明一個類的對象,只需要前向聲明class就行,但是要在類中用到另一個類的方法,就必須要#include<....h>文件;

                       關聯有三種關系,就是類之間有關系,相互知道了解,就是相互引用;聚合就是空心,一個類在另一個類中要用到,但是這個類可以獨立存在;組合就是實心,這個類不能單獨存在;依賴就是要用到這類的方法,去實現一些功能,是一種弱關聯。

 

 

1. 類

 

類(Class)封裝了數據和行為,是面向對象的重要組成部分,它是具有相同屬性、操作、關系的對象集合的總稱。在系統中,每個類都具有一定的職責,職責指的是類要完成什么樣的功能,要承擔什么樣的義務。一個類可以有多種職責,設計得好的類一般只有一種職責。在定義類的時候,將類的職責分解成為類的屬性和操作(即方法)。類的屬性即類的數據職責,類的操作即類的行為職責。設計類是面向對象設計中最重要的組成部分,也是最復雜和最耗時的部分。

 

在軟件系統運行時,類將被實例化成對象(Object),對象對應於某個具體的事物,是類的實例(Instance)。

 

類圖(Class Diagram)使用出現在系統中的不同類來描述系統的靜態結構,它用來描述不同的類以及它們之間的關系。

 

在系統分析與設計階段,類通常可以分為三種,分別是實體類(Entity Class)、控制類(Control Class)和邊界類(Boundary Class),下面對這三種類加以簡要說明:

 

(1) 實體類:實體類對應系統需求中的每個實體,它們通常需要保存在永久存儲體中,一般使用數據庫表或文件來記錄,實體類既包括存儲和傳遞數據的類,還包括操作數據的類。實體類來源於需求說明中的名詞,如學生、商品等。

 

(2) 控制類:控制類用於體現應用程序的執行邏輯,提供相應的業務操作,將控制類抽象出來可以降低界面和數據庫之間的耦合度。控制類一般是由動賓結構的短語(動詞+名詞)轉化來的名詞,如增加商品對應有一個商品增加類,注冊對應有一個用戶注冊類等

 

(3) 邊界類:邊界類用於對外部用戶與系統之間的交互對象進行抽象,主要包括界面類,如對話框、窗口、菜單等。

 

在面向對象分析和設計的初級階段,通常首先識別出實體類,繪制初始類圖,此時的類圖也可稱為領域模型,包括實體類及其它們之間的相互關系。

 

2. 類的UML圖示

 

在UML中,類使用包含類名、屬性和操作且帶有分隔線的長方形來表示,如定義一個Employee類,它包含屬性name、age和email,以及操作modifyInfo(),在UML類圖中該類如圖1所示:

 

 

圖1 類的UML圖示

 

圖1對應的Java代碼片段如下:

 

public class Employee {
	private String name;
	private int age;
	private String email;
	
	public void modifyInfo() {
		......
	}
}

 

在UML類圖中,類一般由三部分組成:

 

(1) 第一部分是類名:每個類都必須有一個名字,類名是一個字符串。

 

(2) 第二部分是類的屬性(Attributes):屬性是指類的性質,即類的成員變量。一個類可以有任意多個屬性,也可以沒有屬性

 

UML規定屬性的表示方式為:

 

可見性 名稱:類型 [ = 缺省值 ]

 

其中:

 

  • “可見性”表示該屬性對於類外的元素而言是否可見,包括公有(public)、私有(private)和受保護(protected)三種,在類圖中分別用符號+、-和#表示。
  • “名稱”表示屬性名,用一個字符串表示。
  • “類型”表示屬性的數據類型,可以是基本數據類型,也可以是用戶自定義類型。
  • “缺省值”是一個可選項,即屬性的初始值。

 

(3) 第三部分是類的操作(Operations):操作是類的任意一個實例對象都可以使用的行為,是類的成員方法。

 

UML規定操作的表示方式為:

 

可見性 名稱(參數列表) [ : 返回類型]

 

其中:

 

  • “可見性”的定義與屬性的可見性定義相同。
  • “名稱”即方法名,用一個字符串表示。
  • “參數列表”表示方法的參數,其語法與屬性的定義相似,參數個數是任意的,多個參數之間用逗號“,”隔開。
  • “返回類型”是一個可選項,表示方法的返回值類型,依賴於具體的編程語言,可以是基本數據類型,也可以是用戶自定義類型,還可以是空類型(void),如果是構造方法,則無返回類型。

 

在類圖2中,操作method1的可見性為public(+),帶入了一個Object類型的參數par,返回值為空(void);操作method2的可見性為protected(#),無參數,返回值為String類型;操作method3的可見性為private(-),包含兩個參數,其中一個參數為int類型,另一個為int[]類型,返回值為int類型。

 

 

圖2 類圖操作說明示意圖

 

由於在Java語言中允許出現內部類,因此可能會出現包含四個部分的類圖,如圖3所示:

 

 

圖3 包含內部類的類圖

 

類與類之間的關系(1)

 

在軟件系統中,類並不是孤立存在的,類與類之間存在各種關系,對於不同類型的關系,UML提供了不同的表示方式。

 

1. 關聯關系

 

關聯(Association)關系是類與類之間最常用的一種關系,它是一種結構化關系,用於表示一類對象與另一類對象之間有聯系,如汽車和輪胎、師傅和徒弟、班級和學生等等。在UML類圖中,用實線連接有關聯關系的對象所對應的類,在使用Java、C#和C++等編程語言實現關聯關系時,通常將一個類的對象作為另一個類的成員變量。在使用類圖表示關聯關系時可以在關聯線上標注角色名,一般使用一個表示兩者之間關系的動詞或者名詞表示角色名(有時該名詞為實例對象名),關系的兩端代表兩種不同的角色,因此在一個關聯關系中可以包含兩個角色名,角色名不是必須的,可以根據需要增加,其目的是使類之間的關系更加明確。

 

如在一個登錄界面類LoginForm中包含一個JButton類型的注冊按鈕loginButton,它們之間可以表示為關聯關系,代碼實現時可以在LoginForm中定義一個名為loginButton的屬性對象,其類型為JButton。如圖1所示:

 

 

圖1 關聯關系實例

 

圖1對應的Java代碼片段如下:

 

public class LoginForm {
private JButton loginButton; //定義為成員變量
……
}

public class JButton {
    ……
}

 

在UML中,關聯關系通常又包含如下幾種形式:

 

(1) 雙向關聯

 

默認情況下,關聯是雙向的。例如:顧客(Customer)購買商品(Product)並擁有商品,反之,賣出的商品總有某個顧客與之相關聯。因此,Customer類和Product類之間具有雙向關聯關系,如圖2所示:

 

 

圖2 雙向關聯實例

 

圖2對應的Java代碼片段如下:

 

public class Customer {
private Product[] products;
……
}

public class Product {
private Customer customer;
……
}

 

(2) 單向關聯

 

類的關聯關系也可以是單向的,單向關聯用帶箭頭的實線表示。例如:顧客(Customer)擁有地址(Address),則Customer類與Address類具有單向關聯關系,如圖3所示:

 

 

圖3 單向關聯實例

 

圖3對應的Java代碼片段如下:

 

public class Customer {
private Address address;
……
}

public class Address {
……
}

 

(3) 自關聯

 

在系統中可能會存在一些類的屬性對象類型為該類本身,這種特殊的關聯關系稱為自關聯。例如:一個節點類(Node)的成員又是節點Node類型的對象,如圖4所示:

 

 

圖4 自關聯實例

 

圖4對應的Java代碼片段如下:

 

public class Node {
private Node subNode;
……
}

 

(4) 多重性關聯

 

多重性關聯關系又稱為重數性(Multiplicity)關聯關系,表示兩個關聯對象在數量上的對應關系。在UML中,對象之間的多重性可以直接在關聯直線上用一個數字或一個數字范圍表示。

 

對象之間可以存在多種多重性關聯關系,常見的多重性表示方式如表1所示:

 

表1 多重性表示方式列表

 

表示方式
多重性說明
1..1
表示另一個類的一個對象只與該類的一個對象有關系
0..*
表示另一個類的一個對象與該類的零個或多個對象有關系
1..*
表示另一個類的一個對象與該類的一個或多個對象有關系
0..1
表示另一個類的一個對象沒有或只與該類的一個對象有關系
m..n
表示另一個類的一個對象與該類最少m,最多n個對象有關系 (m≤n)

 

例如:一個界面(Form)可以擁有零個或多個按鈕(Button),但是一個按鈕只能屬於一個界面,因此,一個Form類的對象可以與零個或多個Button類的對象相關聯,但一個Button類的對象只能與一個Form類的對象關聯,如圖5所示:

 

 

圖5 多重性關聯實例

 

圖5對應的Java代碼片段如下:

 

public class Form {
private Button[] buttons; //定義一個集合對象
……
}

public class Button {
……
}

 

(5) 聚合關系

 

聚合(Aggregation)關系表示整體與部分的關系。在聚合關系中,成員對象是整體對象的一部分,但是成員對象可以脫離整體對象獨立存在。在UML中,聚合關系用帶空心菱形的直線表示。例如:汽車發動機(Engine)是汽車(Car)的組成部分,但是汽車發動機可以獨立存在,因此,汽車和發動機是聚合關系,如圖6所示:

 

 

圖6 聚合關系實例

 

在代碼實現聚合關系時,成員對象通常作為構造方法、Setter方法或業務方法的參數注入到整體對象中,圖6對應的Java代碼片段如下:

 

public class Car {
	private Engine engine;

    //構造注入
	public Car(Engine engine) {
		this.engine = engine;
	}
    
    //設值注入
public void setEngine(Engine engine) {
    this.engine = engine;
}
……
}

public class Engine {
	……
} 

 

(6) 組合關系

 

組合(Composition)關系也表示類之間整體和部分的關系,但是在組合關系中整體對象可以控制成員對象的生命周期,一旦整體對象不存在,成員對象也將不存在,成員對象與整體對象之間具有同生共死的關系。在UML中,組合關系用帶實心菱形的直線表示。例如:人的頭(Head)與嘴巴(Mouth),嘴巴是頭的組成部分之一,而且如果頭沒了,嘴巴也就沒了,因此頭和嘴巴是組合關系,如圖7所示:

 

 

圖7 組合關系實例

 

在代碼實現組合關系時,通常在整體類的構造方法中直接實例化成員類,圖7對應的Java代碼片段如下:

 

public class Head {
	private Mouth mouth;

	public Head() {
		mouth = new Mouth(); //實例化成員類
	}
……
}

public class Mouth {
	……
} 

 

類與類之間的關系(2)

 

2. 依賴關系

 

依賴(Dependency)關系是一種使用關系,特定事物的改變有可能會影響到使用該事物的其他事物,在需要表示一個事物使用另一個事物時使用依賴關系。大多數情況下,依賴關系體現在某個類的方法使用另一個類的對象作為參數。在UML中,依賴關系用帶箭頭的虛線表示,由依賴的一方指向被依賴的一方。例如:駕駛員開車,在Driver類的drive()方法中將Car類型的對象car作為一個參數傳遞,以便在drive()方法中能夠調用car的move()方法,且駕駛員的drive()方法依賴車的move()方法,因此類Driver依賴類Car,如圖1所示:

 

 

圖1 依賴關系實例

 

在系統實施階段,依賴關系通常通過三種方式來實現,第一種也是最常用的一種方式是如圖1所示的將一個類的對象作為另一個類中方法的參數,第二種方式是在一個類的方法中將另一個類的對象作為其局部變量,第三種方式是在一個類的方法中調用另一個類的靜態方法。圖1對應的Java代碼片段如下:

 

public class Driver {
	public void drive(Car car) {
		car.move();
	}
    ……
}

public class Car {
	public void move() {
		......
	}
    ……
}  

 

3. 泛化關系

 

泛化(Generalization)關系也就是繼承關系,用於描述父類與子類之間的關系,父類又稱作基類或超類,子類又稱作派生類。在UML中,泛化關系用帶空心三角形的直線來表示。在代碼實現時,我們使用面向對象的繼承機制來實現泛化關系,如在Java語言中使用extends關鍵字、在C++/C#中使用冒號“:”來實現。例如:Student類和Teacher類都是Person類的子類,Student類和Teacher類繼承了Person類的屬性和方法,Person類的屬性包含姓名(name)和年齡(age),每一個Student和Teacher也都具有這兩個屬性,另外Student類增加了屬性學號(studentNo),Teacher類增加了屬性教師編號(teacherNo),Person類的方法包括行走move()和說話say(),Student類和Teacher類繼承了這兩個方法,而且Student類還新增方法study(),Teacher類還新增方法teach()。如圖2所示:

 

 

圖2 泛化關系實例

 

圖2對應的Java代碼片段如下:

 

//父類
public class Person {
protected String name;
protected int age;

public void move() {
        ……
}

    public void say() {
    ……
    }
}

//子類
public class Student extends Person {
private String studentNo;

public void study() {
    ……
    }
}

//子類
public class Teacher extends Person {
private String teacherNo;

public void teach() {
    ……
    }
}

 

4. 接口與實現關系

 

在很多面向對象語言中都引入了接口的概念,如Java、C#等,在接口中,通常沒有屬性,而且所有的操作都是抽象的,只有操作的聲明,沒有操作的實現。UML中用與類的表示法類似的方式表示接口,如圖3所示:

 

 

圖3 接口的UML圖示

 

接口之間也可以有與類之間關系類似的繼承關系和依賴關系,但是接口和類之間還存在一種實現(Realization)關系,在這種關系中,類實現了接口,類中的操作實現了接口中所聲明的操作。在UML中,類與接口之間的實現關系用帶空心三角形的虛線來表示。例如:定義了一個交通工具接口Vehicle,包含一個抽象操作move(),在類Ship和類Car中都實現了該move()操作,不過具體的實現細節將會不一樣,如圖4所示:

 

 

圖4 實現關系實例

 

實現關系在編程實現時,不同的面向對象語言也提供了不同的語法,如在Java語言中使用implements關鍵字,而在C++/C#中使用冒號“:”來實現。圖4對應的Java代碼片段如下:

 

public interface Vehicle {
public void move();
}

public class Ship implements Vehicle {
public void move() {
    ……
    }
}

public class Car implements Vehicle {
public void move() {
    ……
    }
}

 

實例分析1——登錄模塊

 

某基於C/S的即時聊天系統登錄模塊功能描述如下:

 

用戶通過登錄界面(LoginForm)輸入賬號和密碼,系統將輸入的賬號和密碼與存儲在數據庫(User)表中的用戶信息進行比較,驗證用戶輸入是否正確,如果輸入正確則進入主界面(MainForm),否則提示“輸入錯誤”。

 

根據以上描述繪制初始類圖。

 

參考解決方案:

 

參考類圖如下:

 

 

考慮到系統擴展性,在本實例中引入了抽象數據訪問接口IUserDAO,再將具體數據訪問對象注入到業務邏輯對象中,可通過配置文件(如XML文件)等方式來實現,將具體的數據訪問類類名存儲在配置文件中,如果需要更換新的具體數據訪問對象,只需修改配置文件即可,原有程序代碼無須做任何修改。

 

類說明:

 

類 名
說 明
LoginForm 登錄窗口,省略界面組件和按鈕事件處理方法(邊界類)
LoginBO 登錄業務邏輯類,封裝實現登錄功能的業務邏輯(控制類)
IUserDAO 抽象數據訪問類接口,聲明對User表的數據操作方法,省略除查詢外的其他方法(實體類)
UserDAO 具體數據訪問類,實現對User表的數據操作方法,省略除查詢外的其他方法(實體類)
MainForm 主窗口(邊界類)

 

方法說明:

 

方法名
說 明
LoginForm類的LoginForm()方法 LoginForm構造函數,初始化實例成員
LoginForm類的validate()方法 界面類的驗證方法,通過調用業務邏輯類LoginBO的validate()方法實現對用戶輸入信息的驗證
LoginBO類的validate()方法 業務邏輯類的驗證方法,通過調用數據訪問類的findUserByAccAndPwd()方法驗證用戶輸入信息的合法性
LoginBO類的setIUserDAO()方法 Setter方法,在業務邏輯對象中注入數據訪問對象(注意:此處針對抽象數據訪問類編程
IUserDAO接口的findUserByAccAndPwd()方法 業務方法聲明,通過用戶賬號和密碼在數據庫中查詢用戶信息,判斷該用戶身份的合法性
UserDAO類的findUserByAccAndPwd()方法 業務方法實現,實現在IUserDAO接口中聲明的數據訪問方法

 

實例分析2——注冊模塊

 

某基於Java語言的C/S軟件需要提供注冊功能,該功能簡要描述如下:

 

用戶通過注冊界面(RegisterForm)輸入個人信息,用戶點擊“注冊”按鈕后將輸入的信息通過一個封裝用戶輸入數據的對象(UserDTO)傳遞給操作數據庫的數據訪問類,為了提高系統的擴展性,針對不同的數據庫可能需要提供不同的數據訪問類,因此提供了數據訪問類接口,如IUserDAO,每一個具體數據訪問類都是某一個數據訪問類接口的實現類,如OracleUserDAO就是一個專門用於訪問Oracle數據庫的數據訪問類。

 

根據以上描述繪制類圖。為了簡化類圖,個人信息僅包括賬號(userAccount)和密碼(userPassword),且界面類無需涉及界面細節元素。

 

參考解決方案:

 

在以上功能說明中,可以分析出該系統包括三個類和一個接口,這三個類分別是注冊界面類RegisterForm、用戶數據傳輸類UserDTO、Oracle用戶數據訪問類OracleUserDAO,接口是抽象用戶數據訪問接口IUserDAO。它們之間的關系如下:

 

(1) 在RegisterForm中需要使用UserDTO類傳輸數據且需要使用數據訪問類來操作數據庫,因此RegisterForm與UserDTO和IUserDAO之間存在關聯關系,在RegisterForm中可以直接實例化UserDTO,因此它們之間可以使用組合關聯。

 

(2) 由於數據庫類型需要靈活更換,因此在RegisterForm中不能直接實例化IUserDAO的子類,可以針對接口IUserDAO編程,再通過注入的方式傳入一個IUserDAO接口的子類對象(在本書后續章節中將學習如何具體實現),因此RegisterForm和IUserDAO之間具有聚合關聯關系。

 

(3) OracleUserDAO是實現了IUserDAO接口的子類,因此它們之間具有類與接口的實現關系。

 

(4) 在聲明IUserDAO接口的增加用戶信息方法addUser()時,需要將在界面類中實例化的UserDTO對象作為參數傳遞進來,然后取出封裝在UserDTO對象中的數據插入數據庫,因此addUser()方法的函數原型可以定義為:public boolean addUser(UserDTO user),在IUserDAO的方法addUser()中將UserDTO類型的對象作為參數,故IUserDAO與UserDTO存在依賴關系。

 

通過以上分析,該實例參考類圖如圖1所示:

 

 

圖1 注冊功能參考類圖

 

注意:在繪制類圖或其他UML圖形時,可以通過注釋(Comment)來對圖中的符號或元素進行一些附加說明,如果需要詳細說明類圖中的某一方法的功能或者實現過程,可以使用如圖2所示表示方式:

 

 

圖2 類圖注釋實例

 

實例分析3——售票機控制程序

 

某運輸公司決定為新的售票機開發車票銷售的控制軟件。圖I給出了售票機的面板示意圖以及相關的控制部件。

 

 

圖I 售票機面板示意圖

 

售票機相關部件的作用如下所述:

 

(1) 目的地鍵盤用來輸入行程目的地的代碼(例如,200表示總站)。

 

(2) 乘客可以通過車票鍵盤選擇車票種類(單程票、多次往返票和座席種類)。

 

(3) 繼續/取消鍵盤上的取消按鈕用於取消購票過程,繼續按鈕允許乘客連續購買多張票。

 

(4) 顯示屏顯示所有的系統輸出和用戶提示信息。

 

(5) 插卡口接受MCard(現金卡),硬幣口和紙幣槽接受現金。

 

(6) 打印機用於輸出車票。

 

(7) 所有部件均可實現自檢並恢復到初始狀態。

 

現采用面向對象方法開發該系統,使用UML進行建模,繪制該系統的初始類圖。

 

參考解決方案:

 

參考類圖如下:

 

 

類說明:

 

類 名
說 明
Component 抽象部件類,所有部件類的父類
Keyboard 抽象鍵盤類
ActionKeyboard 繼續/取消鍵盤類
TicketKindKeyboard 車票種類鍵盤類
DestinationKeyboard 目的地鍵盤類
Screen 顯示屏類
CardDriver 卡驅動器類
CashSlot 現金(硬幣/紙幣)槽類
Printer 打印機類
TicketSoldSystem 售票系統類

 

方法說明:

 

方法名
說 明
Component 的init()方法 初始化部件
Component 的doSeltTest()方法 自檢
Keyboard的getSelectedKey()方法 獲取按鍵值
ActionKeyboard的getAction()方法 繼續/取消鍵盤事件處理
TicketKindKeyboard的getTicketKind()方法 車票種類鍵盤事件處理
DestinationKeyboard的getDestinationCode()方法 目的地鍵盤事件處理
Screen的showText()方法 顯示信息
CardDriver的getCredit()方法 獲取金額
CardDriver的debitFare()方法 更新卡余額
CardDriver的ejectMCard()方法 退卡
CashSlot的getCredit()方法 獲取金額
Printer的printTicket()方法 打印車票
Printer的ejectTicket()方法 出票
TicketSoldSystem的verifyCredit()方法 驗證金額
TicketSoldSystem的calculateFare()方法 計算費用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM