設計模式(Design pattern)是一套被反覆使用、多數人知曉的、通過分類編目的、代碼設計經驗的總結。**使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。**設計模式使代碼編制真正工程化,設計模式是軟件工程的基石,如同大廈的一塊塊磚石同樣。只有精通了設計模式,纔敢說真正理解了軟件工程。能夠說,設計模式是每個架構師所必備的技能之一。html
PS:雖然本文代碼是基於Java(但學習設計模式不拘泥於設計模式,不論是何種面嚮對象語言,甚至是非OO語言,我以爲都能從設計模式中窺探一絲代碼架構的奧祕),主要來源於《Head First 設計模式》這本書,並附上了詳細的代碼,強烈建議你們仔細閱讀源代碼。git
在本文中不會列出所有的代碼,重點集中在解釋什麼是設計模式?什麼場景下能夠用這種設計模式?嘗試以實際的問題來驅動學習,使得咱們對設計模式的理解更爲深入而具體。github
讓咱們一塊兒來學習設計模式吧!編程
關於面向對象特性,在《大話設計模式》中有一段極其生動的講解,面向對象就得像活字印刷術同樣:設計模式
第一,要改,只需更改要改之字,此爲可維護;第二,這些字並不是用完此次就無用,徹底能夠在後來的印刷中重複使用,此乃可複用;第三,此詩若要加字,只需另刻字加入便可,這是可擴展;第四,字的排列其實多是豎排多是橫排,此時只需將活字移動就可作到知足排列需求,此是靈活性好。安全
想要精通設計模式,必需要先搞清楚設計模式的設計原則。markdown
PS:怎麼看什麼是「變化」?——若是每次需求一來,某個部分就必須改變,那麼就是不穩定變化的代碼。架構
PS:針對接口編程,實際上是」面向超類型(抽象類、接口)「編程。這個原則讓編程的細節被隱藏,不會由於修改具體實現而常常改動程序結構。函數
PS:雖然繼承接口可讓不一樣子類中實現方式不一樣,可是接口不具備複用性(每個接口的實現代碼都得重寫),而組合卻能夠爲後續的程序設計提供便利。oop
這個能夠看看:www.huaweicloud.com/articles/d5…
PS:交互對象之間應儘量的鬆耦合,以應對後期項目業務邏輯變更的風險。
PS:一旦某個類應該只與它必須知道的類去交互,而不該該知道其餘的類,編程的總原則就是高聚合,低耦合。
PS:不該該存在多於一個致使類變動的緣由,如若否則,就應該將類拆分。
爲了在以後的學習中更好地理解設計模式,咱們須要先學習一下如何繪製、閱讀UML類圖。
爲了更好地理解這本書的例子,須要先對UNL類圖進行簡單的學習。大部分的關係都在下面這幅圖裏面了,多看並記憶便可:
對於類中字段和方法:+ 表示public;-表示private;#表示protected;
繼承關係用空心三角加實線;
接口關係用空心三角加虛線;
關聯關係(如上圖企鵝和睦候,企鵝須要瞭解氣候)用實線箭頭;
PS:關聯能夠當作是,某個類中含有其餘某類的對象。
聚合關係(大雁和雁羣,是一種弱擁有關係)用空心菱形和實線箭頭;
合成(組合)關係(鳥和翅膀是強擁有,即總體和局部的關係)用實心菱形和實線箭頭,兩端的底下的數字,表示幾對幾的關係;
依賴關係(某個類須要基於某個類而存在)用虛線箭頭;
繪製UML類圖,可使用Visio或者Drawio。
設計原則是編程設計過程當中須要時刻考慮的,近乎於道,這些設計原則的組合、碰撞,就產生了許多精彩絕倫、可用性極強的設計模式,是能夠用的術。之因此稱爲模式,是由於在平常的編程開發中,咱們均可以學習、借鑑它們。接下來對設計模式的介紹,我會從:定義、場景、解決的方式方便你們的理解。
定義
單例模式確保一個類只有一個實例,並提供一個全局訪問點。
這定義已經很明確了,那就是全局只能有這個類的一個實例。
場景
單例模式能夠說你們都有所耳聞,甚至實際開發中也用到過(Spring中的組件Bean就是一個一個的單例),當你須要控制某個類的實例數量時,就須要使用單例模式了。
解決
那麼如何讓全局只有一個類呢?
——簡單,將構造函數聲明爲private,這樣就不能在外部經過new來實現了。
問題來了,既然構造函數已經被聲明爲private,怎麼得到該類的對象呢?
——簡單,在該類的內部聲明一個靜態成員函數便可。
單例模式的實現分爲懶漢、餓漢模式。
餓漢模式:類初始化的時候就創建該類的一個實例:
public class SingleObject {
//建立 SingleObject 的一個對象
private static SingleObject instance = new SingleObject();
//讓構造函數爲 private,這樣該類就不會被實例化
private SingleObject(){}
//能夠經過該API獲取惟一可用的對象
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("Hello World!");
}
}
複製代碼
懶漢模式:知道其餘類須要該實例的時候才建立對應的實例:
public class Singleton {
private static Singleton instance;
private Singleton (){}
//須要的時候再建立對應的實例
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
複製代碼
考慮到線程安全,能夠改成:
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
//採用雙檢查鎖,避免頻繁加鎖,性能較好
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
複製代碼
**思考:**單例模式除了能夠保證惟一的實例外,還有什麼好處呢?
——單例模式由於Singleton類封裝它的惟一實例,這樣它能夠嚴格地控制客戶怎樣訪問它以及什麼時候訪問它。簡單地說就是對惟一實例的受控訪問。
《大話設計模式》
《Headfist 設計模式》