咱們在閱讀開源項目時,老是但願能比較高效的整理清楚項目中的各個類之間的關係,那麼有沒有相應的工具能高效、簡潔的表示清楚類關係呢?UML類圖就是一個能夠幫咱們解決此類問題的工具或者方法。markdown
統一建模語言(Unified Modeling Language,縮寫UML)是非專利的第三代建模和規約語言。
UML是一種開放的方法,用於說明、可視化、構建和編寫一個正在開發的、面向對象的、軟件密集系統的製品的開放方法。架構
UML模型和圖形ide
UML分爲模型和圖形兩大類。區分UML模型和UML圖是很是重要的,UML圖(包括用例圖、協做圖、活動圖、序列圖、部署圖、構件圖、類圖、狀態圖)是模型中信息的圖表表達形式,可是UML模型獨立於UML圖存在。工具
在UML系統開發中有三個主要的模型:測試
UML2.2中一共定義了14種圖示。編碼
結構性圖形(Structure diagrams)強調的是系統式的建模:spa
行爲式圖形(Behavior diagrams)強調系統模型中觸發的事件設計
交互性圖形(Interaction diagrams),屬於行爲圖形的子集合,強調系統模型中的資料流程代理
UML展示了一系列最佳工程實踐,這些最佳實踐在對大規模,複雜系統進行建模方面,特別是軟件架構層次方面已經被驗證有效。code
咱們此次介紹的主要是類圖,爲了解析項目的系統結構和架構層次,能夠簡潔明瞭的幫助咱們理解項目中類之間的關係。
類圖的做用:
(1):在軟件工程中,類圖是一種靜態的結構圖,描述了系統的類的集合,類的屬性和類之間的關係,能夠簡化了人們對系統的理解;
(2):類圖是系統分析和設計階段的重要產物,是系統編碼和測試的重要模型。
在UML類圖中,類使用包含類名、屬性(field) 和方法(method) 且帶有分割線的矩形來表示,
舉個栗子。一個Animal類,它包含name,age,state,isPet這4個屬性,以及name相關方法。
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
}
}
複製代碼
對應UML類圖:
可見性 名稱:類型[=默認值]
可見性通常爲public、private和protected,在類圖分別用+、-和#表示,在Swift中沒有與protected徹底對應的可見控制,所以選用的是internal對應爲#;名稱爲屬性的名稱;類型爲數據類型;默認值如變量 age默認值爲0。
可見性 名稱(參數列表 參數1,參數2) :返回類型
可見性如上名稱表達式的介紹,名稱就是方法名,參數列表是可選的項,多參數的話參數直接用英文逗號隔開;返回值也是個可選項,返回值類型能夠說基本的數據類型、用戶自定義類型和void。若是是構造方法,則無返回類型!
類圖中類與類之間的關係主要由:繼承、實現、依賴、關聯、聚合、組合這六大類型。表示方式以下圖:
繼承關係也叫泛化關係,指的是一個類(稱爲子類、子接口)繼承另外的一個類(稱爲父類、父接口)的功能,並能夠增長它本身的新功能的能力,繼承是類與類或者接口與接口之間最多見的關係。
繼承用實線空心箭頭表示,由子類指向父類。
下面寫兩個子類,Fish和Cat分別繼承自Animal。
class Fish: Animal {
public var fishType: String?
func swim() {
}
}
class Cat: Animal {
public var hasFeet: Bool?
func playToy(doll:Doll) {
doll.toyMoved()
}
}
複製代碼
指的是一個class類實現interface接口(能夠是多個)的功能;實現是類與接口之間最多見的關係;在Java中此類關係經過關鍵字implements明確標識,在iOS中我將其理解成代理的實現。
寫一個洋娃娃類Doll,該類遵循了ToyAction協議,實現了玩具移動的方法。
protocol ToyAction {
func toyMoved() -> Void
}
class Doll: NSObject,ToyAction {
public var body: Body?
public var cloth: Cloth?
func toyMoved() {
//洋娃娃玩具動做具體實現
}
}
複製代碼
能夠簡單的理解,就是一個類A使用到了另外一個類B,而這種使用關係是具備偶然性的、、臨時性的、很是弱的,可是B類的變化會影響到A;好比某人要過河,須要借用一條船,此時人與船之間的關係就是依賴;表如今代碼層面,爲類B做爲參數被類A在某個method方法中使用。
在咱們的上述代碼中Cat的playToy方法中參數引用了Doll,所以他們是依賴關係。
他體現的是兩個類、或者類與接口之間語義級別的一種強依賴關係,好比我和個人朋友;這種關係比依賴更強、不存在依賴關係的偶然性、關係也不是臨時性的,通常是長期性的,並且雙方的關係通常是平等的、關聯能夠是單向、雙向的;表如今代碼層面,爲被關聯類B以類屬性的形式出如今關聯類A中,也多是關聯類A引用了一個類型爲被關聯類B的全局變量;
寫一個Person類,他擁有一個寵物貓,他們之間的關係是關聯。
class Head: NSObject {
}
class Person: NSObject {
public var pet: Cat?
public var head: Head?
}
複製代碼
](association.png)
聚合是關聯關係的一種特例,他體現的是總體與部分、擁有的關係,即has-a的關係,此時總體與部分之間是可分離的,他們能夠具備各自的生命週期,部分能夠屬於多個總體對象,也能夠爲多個總體對象共享;好比計算機與CPU、公司與員工的關係等;表如今代碼層面,和關聯關係是一致的,只能從語義級別來區分;
class Cloth: NSObject {
}
class Body: NSObject {
}
複製代碼
在上述代碼中Doll由Body和Cloth組成,且即便失去Cloth,Doll也能夠正常存在。
組合也是關聯關係的一種特例,他體現的是一種contains-a的關係,這種關係比聚合更強,也稱爲強聚合;他一樣體現總體與部分間的關係,但此時總體與部分是不可分的,總體的生命週期結束也就意味着部分的生命週期結束;好比你和你的大腦;表如今代碼層面,和關聯關係是一致的,只能從語義級別來區分;
上述代碼中的Person擁有Head,而且這個總體和部分是不可分割的。
最後來看看這個例子中的總體關係:
其實理解了以後咱們發現仍是很簡單的,學會了以後就能夠投入實踐中了,舉一個簡單第三方庫的類圖例子,下圖是Masonry的類圖整理,能夠看到項目結構很清晰的展現了出來。