設計模式(Design Pattern)
概念:是一套被反覆使用(設計套路),多人知曉,經過分類編目的項目實踐活動中的經驗總結,是某一類典型問題的解決方案
來源:建築的設計模式(裝修房屋,和自已裝修對比)
簡單的講:所謂模式,就是得到很好研究的範例,設計模式就是設計範例。
模式不是框架,也不是過程,也不是簡單的問題解決方案,它必須是典型問題的解決方案,是可以讓學習者反覆使用,有研究價值和交流價值。
模式不能套用,不要以爲在任何一個系統中都要使用某些設計模式。系統的設計也不是含有設計模式越多就越好。
設計模式的本質是面向對象方法的實際運用。具體而言,是封裝,繼承和多態的反覆使用。可以說,現在市面上關於設計模式的書沒有一本適合初學者
要真正理解設計模式就需要透徹理解面向對象設計原則,和麪向對象三大特性。
設計原則
定義:指導面向對象編程的規範,通過遵守設計原則可以得到代碼更好的質量(可閱讀性,可維護性,可擴展新,和可測試性)
1)單一職責原則(SRP)
- 不要存在多於一個導致類變更的原因。簡單的說,即一個類只負責一項職責
- 不能爲圖代碼量少,把不同職責的類合併成一個類
2)開閉原則(OCP)
- 對擴展開發,對修改關閉。
- 主要是爲了向下兼容
3)依賴倒置原則(DIP)
- 高層模塊不應該依賴底層模塊,二者都應該依賴於抽象;抽象不應該依賴於具體,具體應該依賴於抽象
- 所謂的抽象就是定義接口
- 接口和抽象類的區別:接口相當於一種協議(完全的抽象),抽象類:半抽象類(有數據,成員變量)
- 總結:多用抽象的接口來描述相同的動作,降低實現類與類的耦合度,從而實現低耦合高內聚的最高原則。(一開始不應該寫具體的類,應該提取出公共的東西)
4 接口隔離原則(ISP)
- 客戶端(接口的使用者)不應該依賴它不需要的接口;一個類對另一個類的依賴應該建立在最小的接口上。(只需要使用的接口)
5)迪米特原則(LKP):又叫最少接觸原則
- 一個類對自已所依賴的類知道的越少越好,也就是說,對於被依賴的類來說無論邏輯多麼複雜,都儘量的將邏輯封裝在類的內部,對外處理提供public方法,不泄露任何信息。
6)里氏替換原則(LSP)
- 子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法
- 子類可以增加自已特點有的方法
- 當子類的方法重寫父類的方法時,方法的前置條件(方法的參數)要比父類方法更寬鬆
- 當子類的方法實現父類的抽象方法,方法的後置條件(方法的返回值)要比父類的方法更嚴格
- 總結:用盡量不要重寫父類的已經實現的方法,可以接口等其他方法實現。
7)低耦合高內聚(最高原則)
UML(Unified Modeling Language)統一建模語言
概念:是目前面向對象軟件開發流行的用於分析和設計的標準建模語言
畫類圖的工具:EA
- 用例圖:用於分析用戶需求
- 靜態圖:用於顯示系統的靜態結構
- 類 圖:用於分析和設計類與類之間的關係
- 對象圖:用於分析和設計對象與對象之間的關係
- 序列圖:用於描述對象之間的交互順序
- 狀態圖:用於描述對象的所有狀態以及事件發生而引起的狀態之間的轉移
- 協作圖:用於描述對象之間的合作狀態,側重對象之間的消息傳遞
- 活動圖:用於描述用例要求所要進行的活動以及活動時間的約束關係
- 部署圖:用於描述系統中硬件的物理結構
類與類的關係
分類爲:縱向關係和橫向關係
縱向關係
- 繼承關係,它的概念非常明確,也就是面向對象三大特性之一
- UML表示法:實線+三角箭頭(箭頭指向的類爲父類)
- 虛線+三角箭頭(箭頭指向的接口)
橫向關係
-
依賴關係:一個類依賴與另一個類,而另一個類並不依賴其他類,這種關係是一種偶然的,臨時的,非常弱在關係
UML表示法:虛線+箭頭 舉例:人依賴與空氣,但空氣並不依賴人
-
關聯關係:兩個類之間的一種長期的,平等的,可相互調用的關係。分爲單向和雙向的關係
UML表示法:實線+箭頭 舉例:朋友之間的關係
-
聚合關係:是關聯關係的一種特例,它體現的是整體和部分擁有的關係。整體和部分之間是分離的,各有各的生命週期。
UML表示法:空心菱形(整體)+實線+箭頭(部分) 舉例:班級和學員
-
組合關係:是關聯關係的一種特例,它體現的是整體和部分擁有的關係,整體和部分之間是不可分離的,整體的生命週期的結束意味着部分也結束。
UML表示法:實心菱形(整體)+實線+箭頭(部分) 舉例:人與心臟的關係
單列模式(Singleton模式)
1) 定義:是用於創建只有一個實例的類的解決方案
單列模式有兩種實現方式:懶漢式和餓漢式
餓漢式:天生支持線程安全
懶漢式:線程安全要加鎖(線程同步鎖synchronized)
特點:
1.只能實例化一個對象
2.單列類必須自已創建自已唯一實例化對象
3.單列類必須給所有其他對象提供統一的對象獲取方法
2) 優點:
3) 缺點:
4) UML類圖怎麼畫:只有一個類(不用畫)
5) 使用場景:只需要一個類的實例
單例模式實現過程如下:
- 首先,將該類的構造函數私有化(目的是禁止其他程序創建該類的對象);
- 其次,在本類中自定義一個對象(既然禁止其他程序創建該類的對象,就要自己創建一個供程序使用,否則類就沒法用,更不是單例);
- 最後,提供一個可訪問類自定義對象的類成員方法(對外提供該對象的訪問方式)。
直白的講就是,你不能用該類在其他地方創建對象,而是通過該類自身提供的方法訪問類中的那個自定義對象。
那麼問題的關鍵來了,程序調用類中方法只有兩種方式:
- 創建類的一個對象,用該對象去調用類中方法;
- 使用類名直接調用類中方法,格式“類名.方法名()”;
上面說了,構造函數私有化後第一種情況就不能用,只能使用第二種方法。
而使用類名直接調用類中方法,類中方法必須是靜態的,而靜態方法不能訪問非靜態成員變量,因此類自定義的實例變量也必須是靜態的。
這就是單例模式唯一實例必須設置爲靜態的原因。
工廠設計模式
定義:專門負責將大量有共同接口的類實例化;工廠模式可以動態決定將哪一個類實例化,不必事先知道每次要實例化的類
工廠模式有三種形態:
1)簡單工廠模式:又叫靜態工廠方法
2)工廠方法模式:又稱爲多態性工廠模式或虛擬構造子模式
3)抽象工廠模式:又稱工具箱模式
一: 簡單工廠模式:專門定義一個類來負責創建其他類的實例,被創建的類實例通常具有共同的父類
缺點:
- 由於工廠類集中了所有產品的創建邏輯,一旦不能正常,整個系統都要受影響
- 使用簡單工廠模式將會增加系統中類的個數,在一定程度上增加了系統複雜度,性能有所下降
- 系統擴展困難,一旦添加新產品,就不得不修改工廠邏輯,在產品較多的時候,有可能造成工廠邏輯過於複雜,不利於系統的擴展和維護
優點:
- 得到更好的可擴展性,可維護性
- 工廠類還有必要的邏輯判斷,可以決定什麼時候創建哪一個產品,客戶端可以免除直接創建產品而僅僅使用產品就可以了
- 客戶端無需知道所創建的具體產品類名,只需要知道具體產品對應的參數即可,對於一些複雜的類名通過簡單工廠模式可以減少使用者的記憶量
適用場景:
- 工廠類負責創建的對象比較少;由於創建的對象比較少就不會造成工廠方法中的業務邏輯太過複雜
- 客戶端只知道傳入工廠類的參數,對象如何創建對象不關心;客戶端既不需要管線創建細節,甚至連類名都不需要知道。
二: 工廠方法模式
定義:一個用於創建對象的接口或者是抽象類,讓子類決定實例化哪一個類。工廠方法使用一個類的實例延遲到其子類。
優點:
- 在工廠方法中,客戶端只需要知道產品工廠類即可,不需要知道具體的產品類。
- 基於工廠類的多態性設計,是工廠方法模式的關鍵;它能夠使工廠可以自主確定創建何種產品對象,而如何創建產品細節則完全封裝到具體工廠內部。工廠方法模式之所以又稱爲多態工廠模式,正是因爲所以的具體工廠類都具有同一個抽象工廠類。
- 使用工廠方法模式在系統中加入新產品時,無需修改抽象工廠類,也無需修改客戶端,也無需修改其他的具體工廠類和具體產品,而只需要添加具體工廠類和具體產品類,這樣系統的可擴展性也就變得非常好,完全符合“開閉原則”
缺點:
- 在添加新產品是需要編寫新的具體產品類,而且還要提供與之對應的具體工廠類,系統中類的個數將增加兩個類(成對增加),在一定程度上增加了系統的複雜度,會給系統帶來額外的開銷(降低了性能)
使用場景
- 工廠類負責創建的對象比較多,由於具有很好的擴展性,對系統的影響較小
三:抽象工廠模式
定義:提供一個創建一系列或相互依賴的對象接口,而無需指定它們的具體類
優點:
- 隔離了具體類的創建,使得客戶端不需要知道具體產品類
- 當一個產品族中的多個對象被設計一起工作時,它能夠保證客戶端始終只使用同一個產品族中的對象,也就是我們的工廠沒變
缺點:
- 添加新產品對象時,難以擴展抽象工廠以便生產新種類產品
使用場景
- 一個系統的產品族有多於一個產品族,而系統只使用其他某一個產品族的產品