設計模式學習筆記(二):UML與面向對象設計原則

@[TOC]編程

1 UML

1.1 UML

UML(Unified Modeling Language)是統一建模語言,1997年11月UML1.1版本提交給OMG並正式經過,成爲建模語言的個那個也標準。2003年6月UML2.0得到正式經過。設計模式

1.2 UML特性

  • U(Unified):統一,UML融合了多種優秀的面向對象建模方法以及多種獲得承認的軟件工程方法,消除了因方法林立且相互獨立而帶來的種種不便,集衆家之長,股名「統一」。經過統一的表示方法可讓不一樣知識背景的領域專家,系統分析設計人員以及開發人員能夠方便地交流
  • M(Modeling):UML是一種通用的可視化建模語言,不一樣與編程語言,UML經過一些標準的圖形符號和文字來對系統進行建模,用於對軟件進行描述,可視化處理,構造系統製品的文檔。UML適用於各類軟件開發方法,軟件生命週期的各個階段,各類應用領域以及各類開發工具
  • L(Language):UML是一種語言,也就意味着它有屬於本身的標準表達規則,不是一種相似Java,C++的編程語言,而是一種分析設計語言,一種建模語言

1.3 UML結構

UML結構一般包括如下4個部分:視圖,圖,模型元素以及通用機制。bash

1.3.1 視圖

UML視圖用於從不一樣的角度來表示待建模的系統。視圖是由許多圖形組成的一個抽象集合,在創建一個系統模型時,只有經過定義多個視圖,每一個視圖顯示該系統的一個特定方面,才能構造出該系統的完整藍圖。
UML視圖包括:微信

  • 用戶視圖:以用戶的觀點表示系統的目標,是全部視圖的核心,用於描述系統的需求
  • 結構視圖:系統的靜態行爲,描述系統的靜態元素,好比包,類,對象以及它們之間的關係
  • 行爲視圖:系統的動態行爲,描述系統的組成元素在系統運行時的交互關係
  • 實現視圖:系統中邏輯元素的分佈,描述系統中物理文件以及它們之間的關係
  • 環境視圖:系統中物理元素的分佈,描述系統中硬件設備以及他們之間的關係

1.3.2 圖

UML圖是描述UML視圖內容的圖形,UML2.0提供了13種圖,分別是用例圖,類圖,對象圖,包圖,組合結構圖,狀態圖,活動圖,順序圖,通訊圖,定時圖,交互概覽圖,組件圖和部署圖。其中:編程語言

  • 用例圖對應用戶視圖
  • 類圖,對象圖,包圖和組合結構圖對應結構視圖
  • 狀態圖,活動圖,順序圖,通訊圖,定時圖和交互概覽圖對應行爲視圖
  • 組件圖對應實現視圖
  • 部署圖對應環境視圖

1.3.3 模型元素

模型元素是指UML圖中所使用的一些概念,對應於普通的面向對象概念,如類,對象,消息以及這些概念之間的關係,如關聯關係,泛化關係等。ide

1.3.4 通用機制

UML提供的通用機制爲模型元素提供額外的註釋,信息和語義,這些通用機制也提供了擴展機制,容許用戶對UML進行擴展,如定義新的建模元素,擴展原有的語義,添加新的特殊信息來擴展模型元素的規則說明等,以便適用於特定的方法或過程,組織和用戶。函數

2 UML類圖

2.1 類圖

類封裝了數據和行爲,是具備相同屬性,操做,關係的對象集合的總稱。類圖是用出如今系統中不一樣類來描述系統的靜態結構,主要描述不一樣的類以及它們之間的關係。
在UML中,類圖包含類名,屬性以及操做。以下面的Employee類:
在這裏插入圖片描述
類通常由三部分組成:工具

  • 類名
  • 屬性
  • 操做

2.1.1 類名

類名就是類的名字,一個字符串。開發工具

2.1.2 屬性

類的成員變量,通常的格式爲this

可見性 名稱 : 類型 [ = 默認值]

可見性表示該屬性對於類外的元素是否可見,包括:

  • 公有:+
  • 私有:-
  • 受保護:#
  • 包:~

2.1.3 操做

UML規定操做的定義方式爲:

可見性 名稱(參數列表)[ : 返回類型]
  • 可見性與屬性可見性的定義一致
  • 參數列表表示方法的參數,語法與屬性定義相似,用,分隔

2.2 類之間的關係

UML提供了四種不一樣的方式表示類與類之間的關係:

  • 關聯關係
  • 依賴關係
  • 泛化關係
  • 接口與實現關係

下面逐個看一下。

3 關聯關係

關聯關係是一種結構化關係,用於表示一類對象與另外一類對象之間有聯繫。在UML中用實線鏈接有關聯關係的類。能夠在關聯線上標註角色名,關係的兩端表明兩種不一樣的角色,所以在一個關聯關係中能夠包含兩個角色名,角色名不是必須的,但可使類之間的關係更加明確。
例如在一個登陸界面類LoginForm包含一個JButton

在這裏插入圖片描述
UML中關聯一般包括如下六種形式:

  • 雙向關聯
  • 單向關聯
  • 自關聯
  • 多重性關聯
  • 聚合關係
  • 組合關係

3.1 雙向關聯

默認狀況下關聯是雙向的,例如顧客購買商品並擁有商品,反之賣出的商品老是某個顧客與之相關聯:

在這裏插入圖片描述

3.2 單向關聯

關聯也能夠是單向的,在UML中關聯用帶箭頭的實線表示,好比顧客擁有地址:
在這裏插入圖片描述

3.3 自關聯

系統中可能會存在一些類的屬性對象類型爲該類自己,這種特殊的關聯關係爲自關聯,常見於鏈表:
在這裏插入圖片描述

3.4 多重性關聯

多重性關聯又稱爲多重性關聯聯繫,表示兩個關聯對象在數量上的對應關係。在UML中,對象之間的多重性能夠直接在關聯直線上用一個數字或者一個數字範圍來表示。常見的表示方式以下:
在這裏插入圖片描述
例如一個界面能夠具備0個或多個按鈕,可是一個按鈕只能從屬於一個界面:
在這裏插入圖片描述

3.5 聚合關係

聚合關係表示總體與部分的關係,使用空心菱形表示。聚合關係中部分是總體的一部分,可是部分能夠脫離總體獨立存在,好比引擎是汽車的一部分,可是引擎能夠獨立於汽車存在:
在這裏插入圖片描述

3.6 組合關係

組合關係也表示總體與部分之間的關係,可是部分不能脫離總體存在。組合關係使用實心菱形表示。好比人的頭和嘴巴是組合關係:
在這裏插入圖片描述

4 依賴關係

依賴關係是一種使用關係,在須要表示「一個事物使用另外一個事物」時使用依賴關係。UML中依賴關係用帶箭頭的虛線表示,由依賴的一方指向被依賴的一方。例如駕駛員開車,開車須要車,也就是駕駛員依賴於車:
在這裏插入圖片描述

5 泛化關係

泛化關係也就是繼承關係,用於描述父類與之類之間的關係,父類又叫基類或者超類,子類又稱做派生類。UML中泛化關係用帶空心三角形的直線表示,箭頭指向基類:
在這裏插入圖片描述

6 接口與實現關係

不少語言好比Java,C#都有接口的概念,接口一般沒有屬性,全部是操做都是抽象的,只有操做的聲明沒有操做的實現。UML中使用<<Interface>>表示接口:
在這裏插入圖片描述
類與接口之間的實現關係使用空心三角形+虛線表示:

在這裏插入圖片描述

7 面向對象設計原則

7.1 概述

面向對象設計的目標之一是支持可維護性複用,一方面須要實現設計方案或者源代碼的重用,一方面要確保系統可以易於擴展和修改,具備較好的靈活性。面向對象設計原則由此誕生,它們蘊含於不少設計模式中,是從許多方案總結出來的指導性原則。常見的7種面向對象設計原則以下:

  • 單一權責原則
  • 開閉原則
  • 里氏代換原則
  • 依賴倒轉原則
  • 接口隔離原則
  • 合成複用原則
  • 迪米特法則

    7.2 單一職責原則SRP

    單一權責原則(Single Responsibility Principal):一個類只負責一個功能領域中的相應職責。
    或者能夠定義爲:就一個類而言,應該只有一個引發它變化的緣由。

單一權責原則的核心思想是:一個類不能太「累」。一個類(大到模塊,小到方法)承擔的職責越多,被複用的可能性越小,並且一個類承擔的職責過多,就至關於將這些職責耦合在一塊兒,當其中一個職責變化時,可能會影響其餘職責的運做,所以須要將職責分離,封裝在不一樣的類中,即將不一樣的變化緣由封裝在不一樣的類中。單一權責原則是實現高內聚,低耦合的指導方針。

7.3 開閉原則OCP

開閉原則(Open-Closed Principle):一個軟件實體應當對擴展開放,對修改關閉。即軟件實體應儘可能不修改原有代碼的狀況下進行擴展。

其中軟件實體能夠是一個軟件模塊,一個由多個類組成的局部結構或者一個獨立的類。
一個軟件設計符合開閉原則,則能夠很是方便地對其進行擴展,並且在擴展時無須修改現有代碼,使得軟件系統在擁有適應性和靈活性的同時具有較好的穩定性和延續性。

爲了知足開閉原則,須要對系統進行抽象化設計,抽象化是開閉原則的關鍵。能夠經過接口,抽象類等定義抽象層,經過具體類進行擴展,修改系統的行爲時無需修改抽象層,只須要增長新的具體類來實現新的業務功能便可,實如今不修改已有代碼的基礎上擴展系統的功能,達到開閉原則的要求。

7.4 里氏代換原則LSP

里氏代換原則(Liskov Substitution Principle):全部引用基類/父類的地方必須能透明地使用其子類的對象。

簡單地說就是父類出現的地方能夠用子類代替,程序不會產生任何的錯誤和異常。使用里氏代換原則時,應該將父類設計爲抽象類或者接口,讓子類繼承父類或實現父類接口,並實現父類中聲明的方法,運行時,子類實例代替父類實例,能夠很方便地擴展系統的功能,無須修改原有子類的代碼,增長新的功能能夠經過增長一個新的子類來實現。

7.5 依賴倒轉原則DIP

依賴倒轉原則(Dependency Inversion Principal):抽象不該該依賴具體細節,細節應當依賴於抽象,換言之要針對接口編程,而不是針對實現編程。

依賴倒轉原則要求程序在源代碼中傳遞參數時或者在關聯關係中,儘可能引用高層次的抽象層類,即便有接口和抽象類進行變量類型聲明,參數類型聲明,方法返回類型聲明以及數據類型的轉換等,而不是用具體類來作。一個具體類應該只實現接口或者抽象類中聲明過的方法,而不要給出多餘的方法,不然將沒法調用在子類中新增的方法。

在實現依賴倒轉原則時,須要針對抽象層進行編程,而將具體類的對象經過依賴注入(Dependency Injection)的方式注入到其餘對象中。依賴注入是指當一個對象要與其餘對象發生依賴關係時,經過抽象來注入所依賴的對象。經常使用的注入方式包括:

  • 構造注入:經過構造函數來傳入具體類的對象
  • 設值注入(setter注入):經過setter來傳入具體類對象
  • 接口注入:經過實如今接口中聲明的方法來傳入具體類對象

上面的方法在定義時使用抽象類型,在運行時傳入具體類型的對象,由子類對象來覆蓋父類對象 。

7.6 接口隔離原則ISP

接口隔離原則(Interface Segregation Principal):使用多個專門的接口,而不使用單一的總接口,即客戶端不該該依賴於那些它不須要的接口。

也就是說,當一個接口太大時須要劃分爲更小的接口,使用該接口的客戶端僅需知道與之相關的方法。每個接口應該承擔一種相對獨立的角色,這裏的接口有兩層意思:

  • 一種是指一個類型所具備的方法特徵的集合,僅僅是一種邏輯上的抽象
  • 另外一種是指某個語言具體接口的定義,有嚴格的定義和結構,好比Java中的interface

ISP對兩種不一樣含義的表達方式有所不一樣:

  • 當接口理解成一個類型所提供的全部方法特徵的集合時,這就是一種邏輯上的概念,接口的劃分將直接帶來類型的劃分,能夠把接口理解成角色,一個接口只能表明一個角色,每一個角色都有它特定的一個接口,此時這個原則能夠叫「角色隔離原則」
  • 把接口理解成狹義的特定語言的接口,ISP表達的意思是接口僅僅提供客戶端須要的行爲,客戶端不須要的行爲則隱藏起來,應當爲客戶端提供儘量小的接口,而不提供大的總接口。接口應儘可能細化,同時接口中的方法應該儘可能少,每一個接口中只包含一個客戶端(如子模塊或者業務邏輯類)所需的方法便可,這種機制也叫「定製服務」

使用接口隔離原則時,注意控制接口的粒度:

  • 接口過小致使接口氾濫,不利於維護
  • 接口太大將違背ISP,靈活性差,使用不方便

通常而言接口中僅包含爲某一類用戶定製的方法便可。

7.7 合成複用原則CRP

合成複用原則(Composite Reuse Principal):儘可能使用對象組合而不是繼承來達成複用目的。

合成複用原則又叫組合/聚合複用原則(Composition/Aggregate Reuse Principal),就是在一個新對象中經過關聯關係(組合/聚合)對對象進行重用而不是使用繼承。

面向對象設計中,能夠經過兩種方法在不一樣環境中複用已有的設計和實現:

  • 繼承
  • 組合/聚合

7.7.1 繼承

繼承須要嚴格遵循里氏代換原則,有效使用繼承會有助於對問題的理解,下降複雜度,而濫用繼承反而會增長系統構建和維護的難度以及系統的複雜度。繼承主要帶來的問題是會破環系統的封裝性,由於繼承會將基類實現細節暴露給子類,因爲基類內部細節對子類可見,所以叫「白箱複用」。通常而言兩個類之間的關係是「Is-A」關係就可使用繼承。

7.7.2 組合/聚合

儘管能夠經過繼承來對代碼進行復用,通常來講優先考慮組合/聚合。組合/聚合可使系統更加靈活,下降類與類之間的耦合度。因爲新對象能夠直接調用已有對象的功能,這樣作可使成員對象的內部實現細節對新對象不可見,因此這種複用叫「黑箱複用」。通常而言兩個類之間的關係是「Has-A」關係就可使用組合/聚合。

7.8 迪米特法則LoD

迪米特法則(Law of Demeter):一個軟件實體應當儘量少地與其餘實體發生相互做用。

迪米特法則又叫最少知識原則(Least Knowledge Principal,LKP),迪米特法則會對軟件實體之間通訊的寬度與深度進行限制,能夠下降系統的耦合度,使類與類之間保持鬆耦合。
迪米特法則還有幾種定義形式:不要和「陌生人」說話,只與直接朋友通訊。對於一個對象「朋友」能夠是如下幾類:

  • 對象自己(this)
  • 以參數形式傳入的對象
  • 成員對象
  • 若是成員對象是一個集合,那麼集合中的元素也是「朋友」
  • 當前對象所建立的對象

知足上述條件之一便是「朋友」,不然就是「陌生人」,不能和「陌生人」發生直接交互。
迪米特法則要求設計系統時儘可能減小對象之間的交互,經過引入一個合理的中間類來下降現有對象之間的耦合度。應用迪米特法則時須要注意幾點:

  • 優先將類設計爲不變類
  • 類劃分上儘可能建立鬆耦合的類
  • 類結構設計上儘可能下降成員變量和成員函數的訪問權限
  • 在對其餘類的引用上,一個對象對其餘對象的引用應當降到最低

8 總結

在這裏插入圖片描述

在這裏插入圖片描述

若是以爲文章好看,歡迎點贊。

同時歡迎關注微信公衆號:氷泠之路。

在這裏插入圖片描述

相關文章
相關標籤/搜索