@[TOC]編程
UML(Unified Modeling Language)是統一建模語言,1997年11月UML1.1版本提交給OMG並正式經過,成爲建模語言的個那個也標準。2003年6月UML2.0得到正式經過。設計模式
UML結構一般包括如下4個部分:視圖,圖,模型元素以及通用機制。bash
UML視圖用於從不一樣的角度來表示待建模的系統。視圖是由許多圖形組成的一個抽象集合,在創建一個系統模型時,只有經過定義多個視圖,每一個視圖顯示該系統的一個特定方面,才能構造出該系統的完整藍圖。
UML視圖包括:微信
UML圖是描述UML視圖內容的圖形,UML2.0提供了13種圖,分別是用例圖,類圖,對象圖,包圖,組合結構圖,狀態圖,活動圖,順序圖,通訊圖,定時圖,交互概覽圖,組件圖和部署圖。其中:編程語言
模型元素是指UML圖中所使用的一些概念,對應於普通的面向對象概念,如類,對象,消息以及這些概念之間的關係,如關聯關係,泛化關係等。ide
UML提供的通用機制爲模型元素提供額外的註釋,信息和語義,這些通用機制也提供了擴展機制,容許用戶對UML進行擴展,如定義新的建模元素,擴展原有的語義,添加新的特殊信息來擴展模型元素的規則說明等,以便適用於特定的方法或過程,組織和用戶。函數
類封裝了數據和行爲,是具備相同屬性,操做,關係的對象集合的總稱。類圖是用出如今系統中不一樣類來描述系統的靜態結構,主要描述不一樣的類以及它們之間的關係。
在UML中,類圖包含類名,屬性以及操做。以下面的Employee類:
類通常由三部分組成:工具
類名就是類的名字,一個字符串。開發工具
類的成員變量,通常的格式爲this
可見性 名稱 : 類型 [ = 默認值]
可見性表示該屬性對於類外的元素是否可見,包括:
+
-
#
~
UML規定操做的定義方式爲:
可見性 名稱(參數列表)[ : 返回類型]
,
分隔UML提供了四種不一樣的方式表示類與類之間的關係:
下面逐個看一下。
關聯關係是一種結構化關係,用於表示一類對象與另外一類對象之間有聯繫。在UML中用實線鏈接有關聯關係的類。能夠在關聯線上標註角色名,關係的兩端表明兩種不一樣的角色,所以在一個關聯關係中能夠包含兩個角色名,角色名不是必須的,但可使類之間的關係更加明確。
例如在一個登陸界面類LoginForm
包含一個JButton
:
UML中關聯一般包括如下六種形式:
默認狀況下關聯是雙向的,例如顧客購買商品並擁有商品,反之賣出的商品老是某個顧客與之相關聯:
關聯也能夠是單向的,在UML中關聯用帶箭頭的實線表示,好比顧客擁有地址:
系統中可能會存在一些類的屬性對象類型爲該類自己,這種特殊的關聯關係爲自關聯,常見於鏈表:
多重性關聯又稱爲多重性關聯聯繫,表示兩個關聯對象在數量上的對應關係。在UML中,對象之間的多重性能夠直接在關聯直線上用一個數字或者一個數字範圍來表示。常見的表示方式以下:
例如一個界面能夠具備0個或多個按鈕,可是一個按鈕只能從屬於一個界面:
聚合關係表示總體與部分的關係,使用空心菱形表示。聚合關係中部分是總體的一部分,可是部分能夠脫離總體獨立存在,好比引擎是汽車的一部分,可是引擎能夠獨立於汽車存在:
組合關係也表示總體與部分之間的關係,可是部分不能脫離總體存在。組合關係使用實心菱形表示。好比人的頭和嘴巴是組合關係:
依賴關係是一種使用關係,在須要表示「一個事物使用另外一個事物」時使用依賴關係。UML中依賴關係用帶箭頭的虛線表示,由依賴的一方指向被依賴的一方。例如駕駛員開車,開車須要車,也就是駕駛員依賴於車:
泛化關係也就是繼承關係,用於描述父類與之類之間的關係,父類又叫基類或者超類,子類又稱做派生類。UML中泛化關係用帶空心三角形的直線表示,箭頭指向基類:
不少語言好比Java,C#都有接口的概念,接口一般沒有屬性,全部是操做都是抽象的,只有操做的聲明沒有操做的實現。UML中使用<<Interface>>
表示接口:
類與接口之間的實現關係使用空心三角形+虛線表示:
面向對象設計的目標之一是支持可維護性複用,一方面須要實現設計方案或者源代碼的重用,一方面要確保系統可以易於擴展和修改,具備較好的靈活性。面向對象設計原則由此誕生,它們蘊含於不少設計模式中,是從許多方案總結出來的指導性原則。常見的7種面向對象設計原則以下:
單一權責原則(Single Responsibility Principal):一個類只負責一個功能領域中的相應職責。
或者能夠定義爲:就一個類而言,應該只有一個引發它變化的緣由。
單一權責原則的核心思想是:一個類不能太「累」。一個類(大到模塊,小到方法)承擔的職責越多,被複用的可能性越小,並且一個類承擔的職責過多,就至關於將這些職責耦合在一塊兒,當其中一個職責變化時,可能會影響其餘職責的運做,所以須要將職責分離,封裝在不一樣的類中,即將不一樣的變化緣由封裝在不一樣的類中。單一權責原則是實現高內聚,低耦合的指導方針。
開閉原則(Open-Closed Principle):一個軟件實體應當對擴展開放,對修改關閉。即軟件實體應儘可能不修改原有代碼的狀況下進行擴展。
其中軟件實體能夠是一個軟件模塊,一個由多個類組成的局部結構或者一個獨立的類。
一個軟件設計符合開閉原則,則能夠很是方便地對其進行擴展,並且在擴展時無須修改現有代碼,使得軟件系統在擁有適應性和靈活性的同時具有較好的穩定性和延續性。
爲了知足開閉原則,須要對系統進行抽象化設計,抽象化是開閉原則的關鍵。能夠經過接口,抽象類等定義抽象層,經過具體類進行擴展,修改系統的行爲時無需修改抽象層,只須要增長新的具體類來實現新的業務功能便可,實如今不修改已有代碼的基礎上擴展系統的功能,達到開閉原則的要求。
里氏代換原則(Liskov Substitution Principle):全部引用基類/父類的地方必須能透明地使用其子類的對象。
簡單地說就是父類出現的地方能夠用子類代替,程序不會產生任何的錯誤和異常。使用里氏代換原則時,應該將父類設計爲抽象類或者接口,讓子類繼承父類或實現父類接口,並實現父類中聲明的方法,運行時,子類實例代替父類實例,能夠很方便地擴展系統的功能,無須修改原有子類的代碼,增長新的功能能夠經過增長一個新的子類來實現。
依賴倒轉原則(Dependency Inversion Principal):抽象不該該依賴具體細節,細節應當依賴於抽象,換言之要針對接口編程,而不是針對實現編程。
依賴倒轉原則要求程序在源代碼中傳遞參數時或者在關聯關係中,儘可能引用高層次的抽象層類,即便有接口和抽象類進行變量類型聲明,參數類型聲明,方法返回類型聲明以及數據類型的轉換等,而不是用具體類來作。一個具體類應該只實現接口或者抽象類中聲明過的方法,而不要給出多餘的方法,不然將沒法調用在子類中新增的方法。
在實現依賴倒轉原則時,須要針對抽象層進行編程,而將具體類的對象經過依賴注入(Dependency Injection)的方式注入到其餘對象中。依賴注入是指當一個對象要與其餘對象發生依賴關係時,經過抽象來注入所依賴的對象。經常使用的注入方式包括:
上面的方法在定義時使用抽象類型,在運行時傳入具體類型的對象,由子類對象來覆蓋父類對象 。
接口隔離原則(Interface Segregation Principal):使用多個專門的接口,而不使用單一的總接口,即客戶端不該該依賴於那些它不須要的接口。
也就是說,當一個接口太大時須要劃分爲更小的接口,使用該接口的客戶端僅需知道與之相關的方法。每個接口應該承擔一種相對獨立的角色,這裏的接口有兩層意思:
ISP對兩種不一樣含義的表達方式有所不一樣:
使用接口隔離原則時,注意控制接口的粒度:
通常而言接口中僅包含爲某一類用戶定製的方法便可。
合成複用原則(Composite Reuse Principal):儘可能使用對象組合而不是繼承來達成複用目的。
合成複用原則又叫組合/聚合複用原則(Composition/Aggregate Reuse Principal),就是在一個新對象中經過關聯關係(組合/聚合)對對象進行重用而不是使用繼承。
面向對象設計中,能夠經過兩種方法在不一樣環境中複用已有的設計和實現:
繼承須要嚴格遵循里氏代換原則,有效使用繼承會有助於對問題的理解,下降複雜度,而濫用繼承反而會增長系統構建和維護的難度以及系統的複雜度。繼承主要帶來的問題是會破環系統的封裝性,由於繼承會將基類實現細節暴露給子類,因爲基類內部細節對子類可見,所以叫「白箱複用」。通常而言兩個類之間的關係是「Is-A」關係就可使用繼承。
儘管能夠經過繼承來對代碼進行復用,通常來講優先考慮組合/聚合。組合/聚合可使系統更加靈活,下降類與類之間的耦合度。因爲新對象能夠直接調用已有對象的功能,這樣作可使成員對象的內部實現細節對新對象不可見,因此這種複用叫「黑箱複用」。通常而言兩個類之間的關係是「Has-A」關係就可使用組合/聚合。
迪米特法則(Law of Demeter):一個軟件實體應當儘量少地與其餘實體發生相互做用。
迪米特法則又叫最少知識原則(Least Knowledge Principal,LKP),迪米特法則會對軟件實體之間通訊的寬度與深度進行限制,能夠下降系統的耦合度,使類與類之間保持鬆耦合。
迪米特法則還有幾種定義形式:不要和「陌生人」說話,只與直接朋友通訊。對於一個對象「朋友」能夠是如下幾類:
知足上述條件之一便是「朋友」,不然就是「陌生人」,不能和「陌生人」發生直接交互。
迪米特法則要求設計系統時儘可能減小對象之間的交互,經過引入一個合理的中間類來下降現有對象之間的耦合度。應用迪米特法則時須要注意幾點:
若是以爲文章好看,歡迎點贊。
同時歡迎關注微信公衆號:氷泠之路。