我們?cè)陂喿x開源項(xiàng)目時(shí)總是希望能比較高效的整理清楚項(xiàng)目中的各個(gè)類之間的關(guān)系序目,那么有沒有相應(yīng)的工具能高效犀斋、簡(jiǎn)潔的表示清楚類關(guān)系呢奏篙?UML類圖就是一個(gè)可以幫我們解決此類問題的工具或者方法。
1 什么是UML
統(tǒng)一建模語(yǔ)言(Unified Modeling Language关斜,縮寫UML)是非專利的第三代建模和規(guī)約語(yǔ)言示括。
UML是一種開放的方法,用于說明痢畜、可視化垛膝、構(gòu)建和編寫一個(gè)正在開發(fā)的、面向?qū)ο蟮亩∠ ④浖芗到y(tǒng)的制品的開放方法繁涂。
UML模型和圖形
UML分為模型和圖形兩大類。區(qū)分UML模型和UML圖是非常重要的二驰,UML圖(包括用例圖扔罪、協(xié)作圖、活動(dòng)圖桶雀、序列圖矿酵、部署圖唬复、構(gòu)件圖、類圖全肮、狀態(tài)圖)是模型中信息的圖表表達(dá)形式敞咧,但是UML模型獨(dú)立于UML圖存在。
在UML系統(tǒng)開發(fā)中有三個(gè)主要的模型:
- 功能模型:從用戶的角度展示系統(tǒng)的功能辜腺,包括用例圖休建。
- 對(duì)象模型:采用對(duì)象,屬性评疗,操作测砂,關(guān)聯(lián)等概念展示系統(tǒng)的結(jié)構(gòu)和基礎(chǔ),包括類別圖百匆、對(duì)象圖砌些。
- 動(dòng)態(tài)模型:展現(xiàn)系統(tǒng)的內(nèi)部行為。包括序列圖加匈,活動(dòng)圖存璃,狀態(tài)圖。
UML2.2中一共定義了14種圖示雕拼。
結(jié)構(gòu)性圖形(Structure diagrams)強(qiáng)調(diào)的是系統(tǒng)式的建模:
- 靜態(tài)圖(static diagram):包括類圖纵东、對(duì)象圖、包圖
- 實(shí)現(xiàn)圖(implementation diagram):包括組件圖啥寇、部署圖
- 剖面圖
- 復(fù)合結(jié)構(gòu)圖
行為式圖形(Behavior diagrams)強(qiáng)調(diào)系統(tǒng)模型中觸發(fā)的事件
- 活動(dòng)圖
- 狀態(tài)圖
- 用例圖
交互性圖形(Interaction diagrams)偎球,屬于行為圖形的子集合,強(qiáng)調(diào)系統(tǒng)模型中的資料流程
- 通信圖
- 交互概述圖
- 時(shí)序圖
- 時(shí)間圖
2 UML類圖作用
UML展現(xiàn)了一系列最佳工程實(shí)踐示姿,這些最佳實(shí)踐在對(duì)大規(guī)模甜橱,復(fù)雜系統(tǒng)進(jìn)行建模方面逊笆,特別是軟件架構(gòu)層次方面已經(jīng)被驗(yàn)證有效栈戳。
我們這次介紹的主要是類圖,為了解析項(xiàng)目的系統(tǒng)結(jié)構(gòu)和架構(gòu)層次难裆,可以簡(jiǎn)潔明了的幫助我們理解項(xiàng)目中類之間的關(guān)系子檀。
類圖的作用:
(1):在軟件工程中,類圖是一種靜態(tài)的結(jié)構(gòu)圖乃戈,描述了系統(tǒng)的類的集合褂痰,類的屬性和類之間的關(guān)系,可以簡(jiǎn)化了人們對(duì)系統(tǒng)的理解症虑;
(2):類圖是系統(tǒng)分析和設(shè)計(jì)階段的重要產(chǎn)物缩歪,是系統(tǒng)編碼和測(cè)試的重要模型。
?
3 類圖格式
在UML類圖中谍憔,類使用包含類名匪蝙、屬性(field) 和方法(method) 且?guī)в蟹指罹€的矩形來表示主籍,
舉個(gè)栗子。一個(gè)Animal類逛球,它包含name,age和sex這3個(gè)屬性千元,以及name相關(guān)方法。
class Animal: NSObject {
public var name: String?
internal var isPet: Bool?
fileprivate var state: String?
private var age: Int? = 0
override init() {
self.name = "no name"
self.age = 0
self.isPet = true
self.state = "dead"
}
public func getName() -> String {
return self.name!
}
internal func setName(name: String?) {
self.name = name
}
}
對(duì)應(yīng)UML類圖:
[圖片上傳失敗...(image-aa09cc-1563262494896)]
- 類名:粗體颤绕,如果是類是抽象類則類名顯示為斜體幸海!
- 屬性:
可見性 名稱:類型[=默認(rèn)值]
可見性一般為public、private和protected奥务,在類圖分別用+物独、-和#表示,在Swift中沒有與protected完全對(duì)應(yīng)的可見控制汗洒,因此選用的是internal對(duì)應(yīng)為#议纯;名稱為屬性的名稱;類型為數(shù)據(jù)類型溢谤;默認(rèn)值如變量 age默認(rèn)值為0瞻凤。
- 方法:
可見性 名稱(參數(shù)列表 參數(shù)1,參數(shù)2) :返回類型
可見性如上名稱表達(dá)式的介紹世杀,名稱就是方法名阀参,參數(shù)列表是可選的項(xiàng),多參數(shù)的話參數(shù)直接用英文逗號(hào)隔開瞻坝;返回值也是個(gè)可選項(xiàng)蛛壳,返回值類型可以說基本的數(shù)據(jù)類型、用戶自定義類型和void所刀。如果是構(gòu)造方法衙荐,則無返回類型!
4 類與類之間的關(guān)系表達(dá)
類圖中類與類之間的關(guān)系主要由:繼承浮创、實(shí)現(xiàn)忧吟、依賴、關(guān)聯(lián)斩披、聚合溜族、組合這六大類型。表示方式如下圖:
(1) 繼承關(guān)系(Generalization/extends)
繼承關(guān)系也叫泛化關(guān)系垦沉,指的是一個(gè)類(稱為子類煌抒、子接口)繼承另外的一個(gè)類(稱為父類、父接口)的功能厕倍,并可以增加它自己的新功能的能力寡壮,繼承是類與類或者接口與接口之間最常見的關(guān)系。
繼承用實(shí)線空心箭頭表示,由子類指向父類况既。
下面寫兩個(gè)子類屋群,F(xiàn)ish和Cat分別繼承自Animal。
class Fish: Animal {
public var fishType: String?
func swim() {
}
}
class Cat: Animal {
public var hasFeet: Bool?
func playToy(doll:Doll) {
doll.toyMoved()
}
}
(2) 實(shí)現(xiàn)關(guān)系(implements)
指的是一個(gè)class類實(shí)現(xiàn)interface接口(可以是多個(gè))的功能坏挠;實(shí)現(xiàn)是類與接口之間最常見的關(guān)系芍躏;在Java中此類關(guān)系通過關(guān)鍵字implements明確標(biāo)識(shí),在iOS中我將其理解成代理的實(shí)現(xiàn)降狠。
寫一個(gè)洋娃娃類Doll对竣,該類遵循了ToyAction協(xié)議,實(shí)現(xiàn)了玩具移動(dòng)的方法榜配。
protocol ToyAction {
func toyMoved() -> Void
}
class Doll: NSObject,ToyAction {
public var body: Body?
public var cloth: Cloth?
func toyMoved() {
//洋娃娃玩具動(dòng)作具體實(shí)現(xiàn)
}
}
(3) 依賴關(guān)系(Dependency)
可以簡(jiǎn)單的理解否纬,就是一個(gè)類A使用到了另一個(gè)類B,而這種使用關(guān)系是具有偶然性的蛋褥、临燃、臨時(shí)性的、非常弱的烙心,但是B類的變化會(huì)影響到A膜廊;比如某人要過河,需要借用一條船淫茵,此時(shí)人與船之間的關(guān)系就是依賴爪瓜;表現(xiàn)在代碼層面,為類B作為參數(shù)被類A在某個(gè)method方法中使用匙瘪。
在我們的上述代碼中Cat的playToy方法中參數(shù)引用了Doll铆铆,因此他們是依賴關(guān)系。
(4) 關(guān)聯(lián)關(guān)系(Association)
他體現(xiàn)的是兩個(gè)類丹喻、或者類與接口之間語(yǔ)義級(jí)別的一種強(qiáng)依賴關(guān)系薄货,比如我和我的朋友;這種關(guān)系比依賴更強(qiáng)碍论、不存在依賴關(guān)系的偶然性栖榨、關(guān)系也不是臨時(shí)性的欣硼,一般是長(zhǎng)期性的菠秒,而且雙方的關(guān)系一般是平等的隆豹、關(guān)聯(lián)可以是單向先煎、雙向的贼涩;表現(xiàn)在代碼層面,為被關(guān)聯(lián)類B以類屬性的形式出現(xiàn)在關(guān)聯(lián)類A中薯蝎,也可能是關(guān)聯(lián)類A引用了一個(gè)類型為被關(guān)聯(lián)類B的全局變量遥倦;
寫一個(gè)Person類,他擁有一個(gè)寵物貓,他們之間的關(guān)系是關(guān)聯(lián)袒哥。
class Head: NSObject {
}
class Person: NSObject {
public var pet: Cat?
public var head: Head?
}
(5) 聚合關(guān)系(Aggregation)
聚合是關(guān)聯(lián)關(guān)系的一種特例缩筛,他體現(xiàn)的是整體與部分、擁有的關(guān)系堡称,即has-a的關(guān)系瞎抛,此時(shí)整體與部分之間是可分離的,他們可以具有各自的生命周期却紧,部分可以屬于多個(gè)整體對(duì)象桐臊,也可以為多個(gè)整體對(duì)象共享;比如計(jì)算機(jī)與CPU晓殊、公司與員工的關(guān)系等断凶;表現(xiàn)在代碼層面,和關(guān)聯(lián)關(guān)系是一致的巫俺,只能從語(yǔ)義級(jí)別來區(qū)分认烁;
class Cloth: NSObject {
}
class Body: NSObject {
}
在上述代碼中Doll由Body和Cloth組成,且即使失去Cloth介汹,Doll也可以正常存在却嗡。
(6) 組合關(guān)系(Composition)
組合也是關(guān)聯(lián)關(guān)系的一種特例,他體現(xiàn)的是一種contains-a的關(guān)系嘹承,這種關(guān)系比聚合更強(qiáng)稽穆,也稱為強(qiáng)聚合;他同樣體現(xiàn)整體與部分間的關(guān)系赶撰,但此時(shí)整體與部分是不可分的舌镶,整體的生命周期結(jié)束也就意味著部分的生命周期結(jié)束;比如你和你的大腦豪娜;表現(xiàn)在代碼層面餐胀,和關(guān)聯(lián)關(guān)系是一致的,只能從語(yǔ)義級(jí)別來區(qū)分瘤载;
上述代碼中的Person擁有Head否灾,并且這個(gè)整體和部分是不可分割的。
最后來看看這個(gè)例子中的整體關(guān)系:
其實(shí)理解了之后我們發(fā)現(xiàn)還是很簡(jiǎn)單的鸣奔,學(xué)會(huì)了還厚就可以投入實(shí)踐中了墨技,舉一個(gè)簡(jiǎn)單第三方庫(kù)的類圖例子,下圖是Masonry的類圖整理挎狸,可以看到項(xiàng)目結(jié)構(gòu)很清晰的展示了出來扣汪。
?
?
?
?