UML类图最生动的介绍和例子
目的
這篇文章主要是介紹如何使用UML類圖,目的是讓我們能讀懂類圖,以及上手使用類圖。
為什么要使用UML類圖
UML類圖是一種統(tǒng)一建模語言,可以精準(zhǔn)的描述類中擁有的屬性以及方法,以及類與類之間的關(guān)系。
它能夠非常直觀的,通過可視化的方式展示一系列相關(guān)類之間的交互關(guān)系。
在學(xué)習(xí)設(shè)計(jì)模式,或者設(shè)計(jì)自己的類結(jié)構(gòu)時(shí),大都通過UML類圖的形式進(jìn)行展示。
類圖的組成
類圖的組成非常很簡單,只有類 和 類之間的關(guān)系 組成。
類
描述了類內(nèi)部的內(nèi)容。其中包括類的屬性和類的方法,以及他們的可見性。類之間的關(guān)系
描述了類與類之間的交互的方式,包括泛化、實(shí)現(xiàn)、依賴、關(guān)聯(lián)、聚合、組合。那么我們先來看一下關(guān)于類的部分UML是如何描述的,下面是一個(gè)例子
上圖描述了一個(gè)商品(product)類
首先我們看到這個(gè)圖的第一部分
該部分描述了這個(gè)類的名稱,以及它是類型是 類(class)、抽象類(abstract class)還是接口(interface)。
類由C字面表示,抽象類由A表示,接口用I表示。
第二部分描述了類中包含的屬性,屬性的類型以及可見度
屬性可見度+屬性名稱+冒號(hào)+屬性類型,這是UML類圖描述屬性的基本格式。
該例子中,商品(product)類有三個(gè)屬性,分別是名稱(name)、價(jià)格(price)和stock(庫存)。
名稱是String類型的,其余的都是int類型。三個(gè)屬性全部為私有字段。
可見度
關(guān)于可見度有必要說明一下,首先類中的屬性和方法每個(gè)都可以設(shè)置不同的可見度,比如私有的(private)和公共的(public)。在UML類圖中的表述方式有直接通過加(+)減(-)表示的,也有通過圖標(biāo)的形式表示的。
因?yàn)槲覀兊睦邮褂玫氖荘lantUML工具實(shí)現(xiàn)的,所以把該工具表示可見性的規(guī)則放在這里:
下面我們來看類的第三部分
該部分描述類中的方法,相信這部分理解應(yīng)該問題不大
類圖描述方法的格式為:方法可見度+方法名稱+方法入?yún)?/strong>
在例子中,我們提供了三個(gè)屬性的get方法,以及減庫存(reductionStock)方法,它的入?yún)⑹且粋€(gè)整形,入?yún)⒚Q為數(shù)量(num)。它們的可見度均為公共的(public)
那么上述就是關(guān)于類圖中類的描述
類之間的關(guān)系
類之間的關(guān)系稍微復(fù)雜一些,包含泛化、實(shí)現(xiàn)、依賴、關(guān)聯(lián)、聚合、組合。
但實(shí)際上這些組合方式我們?cè)诖a開發(fā)過程中經(jīng)常使用
我們會(huì)成對(duì)的介紹它們,并且提供實(shí)例,方便理解
如果你對(duì)上述關(guān)系已經(jīng)很了解了,可以直接跳到實(shí)例閱讀,否則建議先了解這些關(guān)系的含義
泛化與實(shí)現(xiàn)
泛化就是我們常常講到的繼承(extends),是指我們對(duì)類或抽象類的繼承
實(shí)現(xiàn)(implements)比較好理解,是指一個(gè)類對(duì)接口的實(shí)現(xiàn)。
依賴、關(guān)聯(lián)、聚合、組合
這個(gè)四種關(guān)聯(lián)關(guān)系比較難以區(qū)分,我們讀一段《Java面向?qū)ο缶幊獭穼?duì)其的定義
概念可能比較多,比較抽象,后面我們會(huì)舉例子來解釋
在這里我們只需要明確,這四種關(guān)聯(lián)關(guān)系是層層遞進(jìn)的,耦合度越來越高就可以了。
-
依賴(Dependency)
依賴關(guān)系是類與類之間的聯(lián)接。依賴關(guān)系表示一個(gè)類依賴于另一個(gè)類的定義。依賴關(guān)系在Java語言中體現(xiàn)為局域變量、方法的形參,或者對(duì)靜態(tài)方法的調(diào)用。 -
關(guān)聯(lián)(Association)
依賴關(guān)聯(lián)關(guān)系是類與類之間的聯(lián)接,它使一個(gè)類知道另一個(gè)類的屬性和方法。關(guān)聯(lián)可以是雙向的,也可以是單向的。在Java語言中,關(guān)聯(lián)關(guān)系一般使用成員變量來實(shí)現(xiàn)。 -
聚合(Aggregation)
聚合關(guān)系是關(guān)聯(lián)關(guān)系的一種,是強(qiáng)的關(guān)聯(lián)關(guān)系。聚合是整體和個(gè)體之間的關(guān)系。例如,汽車類與引擎類、輪胎類,以及其它的零件類之間的關(guān)系便整體和個(gè)體的關(guān)系。與關(guān)聯(lián)關(guān)系一樣,聚合關(guān)系也是通過實(shí)例變量實(shí)現(xiàn)的。但是關(guān)聯(lián)關(guān)系所涉及的兩個(gè)類是處在同一層次上的,而在聚合關(guān)系中,兩個(gè)類是處在不平等層次上的,一個(gè)代表整體,另一個(gè)代表部分。 -
組合(Composition)
組合關(guān)系是關(guān)聯(lián)關(guān)系的一種,是比聚合關(guān)系強(qiáng)的關(guān)系。它要求普通的聚合關(guān)系中代表整體的對(duì)象負(fù)責(zé)代表部分對(duì)象的生命周期,組合關(guān)系是不能共享的。代表整體的對(duì)象需要負(fù)責(zé)保持部分對(duì)象和存活,在一些情況下將負(fù)責(zé)代表部分的對(duì)象湮滅掉。代表整體的對(duì)象可以將代表部分的對(duì)象傳遞給另一個(gè)對(duì)象,由后者負(fù)責(zé)此對(duì)象的生命周期。換言之,代表部分的對(duì)象在每一個(gè)時(shí)刻只能與一個(gè)對(duì)象發(fā)生組合關(guān)系,由后者排他地負(fù)責(zé)生命周期。部分和整體的生命周期一樣。
——摘自《Java面向?qū)ο缶幊獭?#xff0c;作者:孫衛(wèi)琴
類關(guān)系的實(shí)例
OK那么我們接下來逐個(gè)解釋
1. 泛化
泛化符號(hào)是以三角箭頭以及實(shí)線組成
該例子中,狗(dog)類繼承了動(dòng)物類(animal)
實(shí)現(xiàn)代碼
class main{class animal {public void move(){print("move")}}class dog extends animal {public void bark(){print("wangwangwagn")}} }2. 實(shí)現(xiàn)
泛化符號(hào)是以三角箭頭以及虛線組成
該例子中,汽車類(car)實(shí)現(xiàn)了運(yùn)輸接口(Transport)
實(shí)現(xiàn)代碼
class Main{interface Transport{void deliver();}class Car implements Transport{public void deliver(){print("deliver to destination")}} }3. 依賴
依賴關(guān)系表示一個(gè)類依賴于另一個(gè)類的定義,即一個(gè)類的實(shí)現(xiàn)需要另一個(gè)類的協(xié)助。依賴關(guān)系通常是局部的,在程序中的體現(xiàn)往往是A類的某個(gè)方法需要傳入一個(gè)B類,或者A類在某個(gè)方法中創(chuàng)建了B類局部變量。
依賴是通過箭頭+虛線表示的
在該例子中,我們有一個(gè)人(People)類,它有兩個(gè)方法打獵(hunting)和吃飯(eat)。
其中打獵方法調(diào)用時(shí)需要傳入槍(Gun)類,吃飯方法調(diào)用時(shí)需要傳入食物(Food)類。
此時(shí),人(People)類就是的實(shí)現(xiàn)就依賴于槍(Gun)和食物(Food)類。
代碼實(shí)現(xiàn)
class Main{class Gun{public void get(){print("這是一把槍!"); }}class Food{public void get(){print("這是一份食物!"); }}class People{public void hunting(Gun gun){gun.get();print("獲取槍支,開始打獵!");}public void eat(Food food){food.get();print("獲取食物,開始吃飯!");}}}4. 關(guān)聯(lián)
關(guān)聯(lián)關(guān)系比依賴關(guān)系更近一步,它使一個(gè)類知道另一個(gè)類的屬性和方法。
在代碼的體現(xiàn)上通常是作為類中的成員變量存在。
關(guān)聯(lián)是通過箭頭+實(shí)線表示的
在該例子中,我們擁有警察類(Police)和槍(Gun)類
警察類通過成員變量gun與槍類進(jìn)行關(guān)聯(lián)
警察在調(diào)用waring()和shooting()方法時(shí)使用了gun。
區(qū)別
這里需要注意的是與上一個(gè)例子的區(qū)別
這兩個(gè)例子中都存在槍(Gun)類,但不同的是警察在是一直要佩戴槍支的
而普通人只有在打獵場(chǎng)景時(shí)(對(duì)應(yīng)調(diào)用hunting()方法時(shí))才需要槍
普通人與槍的關(guān)系時(shí)依賴關(guān)系
而警察與槍的關(guān)系時(shí)關(guān)聯(lián)
代碼實(shí)現(xiàn)
class Main{class Gun{public void show(){print("展示槍支")}public void shooting(){print("發(fā)射子彈!")}}class Police{private Gun gun;public setGun(gun){this.gun = gun;}//警察通過持槍警告罪犯public void waring(){gun.show()print("不許動(dòng)!")}//警察使用槍支進(jìn)行射擊public void shooting(){gun.shooting()}}}5. 聚合
聚合關(guān)系是關(guān)聯(lián)關(guān)系的一種,是強(qiáng)的關(guān)聯(lián)關(guān)系。聚合強(qiáng)調(diào)的是對(duì)象之前整體與部分的依賴關(guān)系。
與關(guān)聯(lián)關(guān)系一樣,聚合關(guān)系也是通過實(shí)例變量實(shí)現(xiàn)的。但是關(guān)聯(lián)關(guān)系所涉及的兩個(gè)類是處在同一層次上的,而在聚合關(guān)系中,兩個(gè)類是處在不平等層次上的,一個(gè)代表整體,另一個(gè)代表部分
聚合是通過空心菱形+實(shí)線表示的
該例子中,汽車(Car)類與引擎(Engine)類屬于聚合的關(guān)系
其中Engine屬于Car的一部分,雙方的關(guān)系不是對(duì)等的關(guān)系
代碼實(shí)現(xiàn)
class Main{public class Engine{public void on(){print("引擎啟動(dòng)");}}public class Car{Engine engine;void setEngine(Engine engine){this.engine = engine;}public void show(){engine.show();pring("開車去兜風(fēng)");}}void Main(){Car car = new Car();car.setEngine(new Engine());car.show();}}6. 組合
組合關(guān)系又是聚合關(guān)系的加強(qiáng)
其中組合關(guān)系強(qiáng)調(diào)的是整體對(duì)象負(fù)責(zé)管理部分對(duì)象的生命周期
而且在整個(gè)過程中,代表部分的對(duì)象應(yīng)只屬于一個(gè)整體對(duì)象。
組合是通過實(shí)心菱形+實(shí)線表示的
該例子中,學(xué)校(School)類與班級(jí)(Classes)類屬于組合的關(guān)系
學(xué)校構(gòu)建了所有的班級(jí)集合,并管理它們的生命周期。
而班級(jí)只屬于某所學(xué)校,在整個(gè)生命周期中,除非有必要(在本實(shí)例中沒有這個(gè)必要),否則學(xué)校類甚至可以不暴露任何有關(guān)班級(jí)的實(shí)體。
也就是說,學(xué)校類可以擁有對(duì)班級(jí)類完整的控制權(quán)。
代碼實(shí)現(xiàn)
class Main{public class School{private Stirng name;private List<Classes> classesList;public School(int sumClasses){classesList = ArrayList<>();for(int i = 0 ; i < sumClasses ; i ++){classesList.add(new Classes(sumClasses+"班級(jí)"));}}public void giveLessons(){print("上課啦!");for(Classes Classes : classesList){Classes.giveLessons();}}}public class Classes{private Stirng name;public Classes (String name){this.name = name;}public void giveLessons(){print(name+"班上課啦!");}}void Main(){new School().giveLessons();}}畫圖軟件
簡單的介紹一款畫圖軟件,叫PlantUML
這個(gè)軟件的優(yōu)點(diǎn)是通過簡單的代碼就能生成UML圖,而且支持中文,官網(wǎng)有很多詳細(xì)的使用方法和例子
對(duì)比較熟悉代碼的朋友們來說,這個(gè)畫圖軟件還是比較好用的(其實(shí)都不應(yīng)該叫畫圖軟件了lol)
但是如果是對(duì)代碼不是很理解,或者不能很方便的用代碼作為生產(chǎn)力的同學(xué)
還是建議根據(jù)自己的系統(tǒng)平臺(tái)找一找別的畫圖軟件,這里就不展開了
結(jié)語
OK那么關(guān)于UML類圖的介紹就到這里了。這篇文章斷斷續(xù)續(xù)寫了蠻久,主要是因?yàn)閭€(gè)人原因,一直覺得有些例子沒有很好的詮釋這些關(guān)系中的區(qū)別,但是一耽擱就幾個(gè)月沒再動(dòng)筆了。
這篇文章的目的主要是想通過比較簡單的語言加上例子,讓大家對(duì)這些關(guān)系有一個(gè)比較清楚的認(rèn)識(shí)。
如果覺得文章中有錯(cuò)誤的地方請(qǐng)及時(shí)指正,謝謝!
總結(jié)
以上是生活随笔為你收集整理的UML类图最生动的介绍和例子的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt程序移植
- 下一篇: pc 装MAC 资料