設計模式及單例模式
設計模式概念
模式的起源
設計模式這一概念,起源於建築領域,是由Christopher Alexander(克里斯托佛·亞歷山大)及其團隊,長時間通過對建築行業的調查研究,總結了建築行業可重複複用的解決方案,並記錄在《建築的永恆之道》中。
在書中,對模式的定義是:每個模式都描述了一個在環境中不斷出現的問題,然後描述了該問題的解決方案核心,通過這種方式,可以無數次地重用那些已有的成功的解決方案,無須再重複相同的工作。
簡單表述就是:模式是在特定環境下解決某類重複出現問題的一套成功或有效的解決方案。
從模式Pattern的定義中可以看到,每個模式是在特定的環境下才有效,學習模式,除了瞭解模式本身的,還得了解這個模式在什麼環境下才能使用
模式 = 套路
引入模式到軟體工程
在1994年,四人組(Gang of Four),歸納並發表了 23 種在軟體開發中使用頻率較高的設計模式,把模式的概念引入軟體工程中,即軟體模式(Software Patterns)。當然,模式的概念不止存在於設計模式中,還包括了架構模式、分析模式、過程模式等,在軟體週期的每個階段,都有相應被總結的模式。
什麼是設計模式
設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、程式碼設計經驗的總結。使
用設計模式是為了可重用程式碼、讓程式碼更容易被他人理解、保證程式碼可擴充套件性和可維護性。通用設計模式有23個,每一個設計模式都是某一類典型問題的解決方案。
設計模式的本質
設計模式的本質是面向物件程式設計技術的熟練和靈活運用,要真正理解設計模式就需要透徹理解面向物件設計原則和麵向物件三大特性(封裝、繼承、多型)。
所有設計模式的書籍都是面向有一定 Java 語言基礎和一定專案程式設計經驗的讀者
學習設計模式的誤區
不要以為在任何一個系統中都要使用設計模式,系統也不是套用設計模式越多越好。濫用設計模式將增加系統複雜度,降低系統的可維護性。
學習設計模式五要素
- 名稱:每一種設計模式都有名稱,都是經過專門分類編目的,以便於學習交流
- 問題:每一種設計模式都是某一類典型問題的解決方案
- 實現:每一種設計模式都有一種或多種程式碼實現方式(UML類圖)
- 優缺點:每一種設計模式都存在優缺點(沒有完美無缺的解決方案)
- 適用場景:每一種設計模式都有其常見典型的適用場景
單例設計模式
定義
單例設計模式是 23 種設計模式中最簡單、使用最頻繁的設計模式,它為系統中的類只允許例項化唯一一個物件這類典型問題提供解決方案。
單例模式的實現方式有好幾種,這裡主要介紹三種:懶漢式單例、餓漢式單例、登記式單例。
特點
1、單例類只能有例項化一個物件。
2、單例類必須自己建立自己的唯一例項化物件。
3、單例類必須給所有其他物件提供統一的物件引用方法。
單例實現方式
- 懶漢式
public class IdlerSingleton {
private static IdlerSingleton singleton = null;
private IdlerSingleton() {
}
public static synchronized IdlerSingleton getInstance() { // 執行緒同步
if ( null == singleton) {
singleton = new IdlerSingleton();
}
return singleton;
}
}
優點:
避免了餓漢式的那種在沒有用到的情況下建立事例,資源利用率高,不執行getInstance()就不會被例項,可以執行該類的其他靜態方法。
缺點:
懶漢式在單個執行緒中沒有問題,但多個執行緒同事訪問的時候就可能同事建立多個例項,而且這多個例項不是同一個物件,雖然後面建立的例項會覆蓋先建立的例項,但是還是會存在拿到不同物件的情況。解決這個問題的辦法就是加鎖synchonized,第一次載入時不夠快,多執行緒使用不必要的同步開銷大。
- 餓漢式(推薦)
餓漢式在類建立的同時就已經建立好一個靜態的物件供系統使用,以後不再改變,所以天生是執行緒安全的。
public class HungrySingleton {
private static final HungrySingleton SINGLETON = new HungrySingleton();
private HungrySingleton() {
}
public HungrySingleton getInstance() {
return SINGLETON;
}
}
優點
- 執行緒安全
- 在類載入的同時已經建立好一個靜態物件,呼叫時反應速度快
缺點
資源效率不高,可能 getInstance() 永遠不會執行到,但執行該類的其他靜態方法或者載入了該類(class.forName),那麼這個例項仍然初始化
- 靜態內部類
class Test {
private Test() {
}
private static class SingletonHelp {
static Test instance = new Test();
}
public static Test getInstance() {
return SingletonHelp.instance;
}
}
優點:資源利用率高,不執行getInstance()不被例項,可以執行該類其他靜態方法
缺點:第一次載入時反應不夠快
總結
一般採用餓漢式,若對資源十分在意可以採用靜態內部類,不建議採用懶漢式