1. 程式人生 > >【設計模式】—-(1)單例模式(建立型)

【設計模式】—-(1)單例模式(建立型)

概念:  java中單例模式是一種常見的設計模式,單例模式的寫法有好幾種,這裡主要介紹三種:懶漢式單例、餓漢式單例、登記式單例。  單例模式有以下特點:  1、單例類只能有一個例項。  2、單例類必須自己建立自己的唯一例項。  3、單例類必須給所有其他物件提供這一例項。
  單例模式確保某個類只有一個例項,而且自行例項化並向整個系統提供這個例項。在計算機系統中,執行緒池、快取、日誌物件、對話方塊、印表機、顯示卡的驅動程式物件常被設計成單例。這些應用都或多或少具有資源管理器的功能。每臺計算機可以有若干個印表機,但只能有一個Printer Spooler,以避免兩個列印作業同時輸出到印表機中。每臺計算機可以有若干通訊埠,系統應當集中管理這些通訊埠,以避免一個通訊埠同時被兩個請求同時呼叫。總之,選擇單例模式就是為了避免不一致狀態,避免政出多頭。


一、懶漢式單例

[java] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. //懶漢式單例類.在第一次呼叫的時候例項化自己 
  2. publicclass Singleton {  
  3.     private Singleton() {}  
  4.     privatestatic Singleton single=null;  
  5.     //靜態工廠方法 
  6.     publicstatic Singleton getInstance() {  
  7.          if (single == null) {    
  8.              single = new Singleton();  
  9.          }    
  10.         return single;  
  11.     }  
  12. }  
Singleton通過將構造方法限定為private避免了類在外部被例項化,在同一個虛擬機器範圍內,Singleton的唯一例項只能通過getInstance()方法訪問。

(事實上,通過Java反射機制是能夠例項化構造方法為private的類的,那基本上會使所有的Java單例實現失效。此問題在此處不做討論,姑且掩耳盜鈴地認為反射機制不存在。)

但是以上懶漢式單例的實現沒有考慮執行緒安全問題,它是執行緒不安全的,併發環境下很可能出現多個Singleton例項,要實現執行緒安全,有以下三種方式,都是對getInstance這個方法改造,保證了懶漢式單例的執行緒安全,如果你第一次接觸單例模式,對執行緒安全不是很瞭解,可以先跳過下面這三小條,去看餓漢式單例,等看完後面再回頭考慮執行緒安全的問題:

1、在getInstance方法上加同步

[java] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicstaticsynchronized Singleton getInstance() {  
  2.          if (single == null) {    
  3.              single = new Singleton();  
  4.          }    
  5.         return single;  
  6. }  

2、雙重檢查鎖定

[java] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicstatic Singleton getInstance() {  
  2.         if (singleton == null) {    
  3.             synchronized (Singleton.class) {    
  4.                if (singleton == null) {    
  5.                   singleton = new Singleton();   
  6.                }    
  7.             }    
  8.         }    
  9.         return singleton;   
  10.     }  

3、靜態內部類

[java] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicclass Singleton {    
  2.     privatestaticclass LazyHolder {    
  3.        privatestaticfinal Singleton INSTANCE = new Singleton();    
  4.     }    
  5.     private Singleton (){}    
  6.     publicstaticfinal Singleton getInstance() {    
  7.        return LazyHolder.INSTANCE;    
  8.     }    
  9. }    
這種比上面1、2都好一些,既實現了執行緒安全,又避免了同步帶來的效能影響。

二、餓漢式單例

[java] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. //餓漢式單例類.在類初始化時,已經自行例項化 
  2. publicclass Singleton1 {  
  3.     private Singleton1() {}  
  4.     privatestaticfinal Singleton1 single = new Singleton1();  
  5.     //靜態工廠方法 
  6.     publicstatic Singleton1 getInstance() {  
  7.         return single;  
  8.     }  
  9. }  
餓漢式在類建立的同時就已經建立好一個靜態的物件供系統使用,以後不再改變,所以天生是執行緒安全的。

三、登記式單例(可忽略)

[java] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. //類似Spring裡面的方法,將類名註冊,下次從裡面直接獲取。
  2. publicclass Singleton3 {  
  3.     privatestatic Map<String,Singleton3> map = new HashMap<String,Singleton3>();  
  4.     static{  
  5.         Singleton3 single = new Singleton3();  
  6.         map.put(single.getClass().getName(), single);  
  7.     }  
  8.     //保護的預設構造子
  9.     protected Singleton3(){}  
  10.     //靜態工廠方法,返還此類惟一的例項
  11.     publicstatic Singleton3 getInstance(String name) {  
  12.         if(name == null) {  
  13.             name = Singleton3.class.getName();  
  14.             System.out.println("name == null"+"--->name="+name);  
  15.         }  
  16.         if(map.get(name) == null) {  
  17.             try {  
  18.                 map.put(name, (Singleton3) Class.forName(name).newInstance());  
  19.             } catch (InstantiationException e) {  
  20.                 e.printStackTrace();  
  21.             } catch (IllegalAccessException e) {  
  22.                 e.printStackTrace();  
  23.             } catch (ClassNotFoundException e) {  
  24.                 e.printStackTrace();  
  25.             }  
  26.         }  
  27.         return map.get(name);  
  28.     }  
  29.     //一個示意性的商業方法
  30.     public String about() {      
  31.         return"Hello, I am RegSingleton.";      
  32.     }      
  33.     publicstaticvoid main(String[] args) {  
  34.         Singleton3 single3 = Singleton3.getInstance(null);  
  35.         System.out.println(single3.about());  
  36.     }  
  37. }  

登記式單例實際上維護了一組單例類的例項,將這些例項存放在一個Map(登記薄)中,對於已經登記過的例項,則從Map直接返回,對於沒有登記的,則先登記,然後返回。

這裡我對登記式單例標記了可忽略,我的理解來說,首先它用的比較少,另外其實內部實現還是用的餓漢式單例,因為其中的static方法塊,它的單例在類被裝載的時候就被例項化了。

餓漢式和懶漢式區別

從名字上來說,餓漢和懶漢,

餓漢就是類一旦載入,就把單例初始化完成,保證getInstance的時候,單例是已經存在的了,

而懶漢比較懶,只有當呼叫getInstance的時候,才回去初始化這個單例。

另外從以下兩點再區分以下這兩種方式:

1、執行緒安全:

餓漢式天生就是執行緒安全的,可以直接用於多執行緒而不會出現問題,

懶漢式本身是非執行緒安全的,為了實現執行緒安全有幾種寫法,分別是上面的1、2、3,這三種實現在資源載入和效能方面有些區別。

2、資源載入和效能:

餓漢式在類建立的同時就例項化一個靜態物件出來,不管之後會不會使用這個單例,都會佔據一定的記憶體,但是相應的,在第一次呼叫時速度也會更快,因為其資源已經初始化完成,

而懶漢式顧名思義,會延遲載入,在第一次使用該單例的時候才會例項化物件出來,第一次呼叫時要做初始化,如果要做的工作比較多,效能上會有些延遲,之後就和餓漢式一樣了。

至於1、2、3這三種實現又有些區別,

第1種,在方法呼叫上加了同步,雖然執行緒安全了,但是每次都要同步,會影響效能,畢竟99%的情況下是不需要同步的,

第2種,在getInstance中做了兩次null檢查,確保了只有第一次呼叫單例的時候才會做同步,這樣也是執行緒安全的,同時避免了每次都同步的效能損耗

第3種,利用了classloader的機制來保證初始化instance時只有一個執行緒,所以也是執行緒安全的,同時沒有效能損耗,所以一般我傾向於使用這一種。

什麼是執行緒安全?

如果你的程式碼所在的程序中有多個執行緒在同時執行,而這些執行緒可能會同時執行這段程式碼。如果每次執行結果和單執行緒執行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是執行緒安全的。

或者說:一個類或者程式所提供的介面對於執行緒來說是原子操作,或者多個執行緒之間的切換不會導致該介面的執行結果存在二義性,也就是說我們不用考慮同步的問題,那就是執行緒安全的。

應用

以下是一個單例類使用的例子,以懶漢式為例,這裡為了保證執行緒安全,使用了雙重檢查鎖定的方式

[java] view plain copy  print?在CODE上檢視程式碼   
 
 </div> 
 <div class=

相關推薦

設計模式—-1模式建立

概念:  java中單例模式是一種常見的設計模式,單例模式的寫法有好幾種,這裡主要介紹三種:懶漢式單例、餓漢式單例、登記式單例。  單例模式有以下特點:  1、單例類只能有一個例項。  2、單例類必須自己建立自己的唯一例項。  3、單例類必須給所有其他物件提供這一例項。 

從頭學習設計模式——模式

一、引入   單例模式作為23種設計模式中的最基礎的一種模式,在平時開發中應用也非常普遍。到底哪些類應該設計成單例的呢,我們來舉個最通俗的例子。在一個父容器中單擊某個選單項開啟一個子視窗,如果不使用單例又沒有作選單項的可用控制的話,每次單擊選單項都會開啟一個新視窗。這不僅會浪費記憶體資源,在程式邏輯

23種設計模式1-模式

如果 static 拓展 銷毀 jvm垃圾收集器 單例類 不為 全局 返回值 定義: 單例模式,是一種常用的軟件設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。通過單例模式可以保證系統中一個類只有一個實例。即一個類只有一個對象實例。 特點:

設計模式1----模式

內存 內部 gin strong 系統 方法 main 重新 out 簡介: 單例模式(Singleton)是一種常用的軟件設計模式,在它的核心結構中只包含一個被稱為單例的特殊類。 定義: 確保一個類只有一個實例,而且自行實例化並向整個系統提供這個實例。 單例模式 單例模式

android開發學習 ------- android中的模式 詳解

lan post tail -- and 使用 href details android開發 https://blog.csdn.net/u011418943/article/details/60139644 這篇文章 前因後果 都說出來了 ,值得學習。 htt

設計模式1——模式

虛擬 span 源碼 加載 定義 實例變量 不能 內存 而且 在Java開發過程中,很多場景下都會碰到或要用到單例模式,在設計模式裏也是經常作為指導學習的熱門模式之一,相信每位開發同事都用到過。我們總是沿著前輩的足跡去做設定好的思路,往往沒去探究為何這麽做,所以這篇文章對單

java設計模式---1模式

單例模式 定義: 確保一個類只有一個例項, 而且自行例項化並向整個系統提供這個例項 保證只有一個例項,只能是不讓外面訪問的類的構造方法,所以就構造方法寫成私有的,向整個系統提供一個例項那麼就只能定義一個static的例項返回回去了,所以程式碼可以這樣寫: public class Sin

golang設計模式1模式

做軟體開發工程師兩三年了,接觸到的第一種設計模式就是單例模式,記得當年第一份工作第一個任務就是用C語言寫一個網路抓包的工具。那時候坐旁邊的同事就問,你們兩寫的這個工具有用到什麼設計模式嗎?當時一臉懵,設計模式是個什麼東西,那時候他說計算機專業有學過,但是看公司版

java設計模式1/23-模式Singleton pattern

java建立型模式之一: 單例模式(Singleton pattern) 什麼是設計模式? 是一套被反覆使用、多人知曉的、經過分類編目的程式碼設計經驗的總結。 使用設計模式是為了可重用程式碼,讓程式碼更容易被他人理解、保證程式碼的可靠性。 有些物件我們只需要一個,比如:

設計模式1模式

**剛接觸設計模式的時候感覺很高大上的感覺,老師怎麼寫程式碼,就怎麼寫,沒有徹底的領會設計模式的深層次的思想。藉著複習的時間總結一下。** 1. 介紹:設計模式其實就是一種反覆使用的,多數人知曉的,經過分類編輯的程式碼設計經驗的總結。它停留在思想和經驗的層面

設計模式---模式

由於 div 懶漢式 其它 ins class single sin pub 1、簡介   作為對象的創建模式,單例模式確保某一個類只有一個實例,並且自行實例化並向整個系統提供這個實例,這個類稱為單例類 2、單例模式有以下三個特點   2.1、單例類只能有一個實例   

設計模式模式

分享 公有 交互 線程 加鎖 解決 操作 編譯 進入 1.單例模式(Singleton):由於某種需要,要保證一個類在程序的生命周期中只有一個實例,並提供一個該實例的全局訪問方法。 2.單例模式(Singleton)結構圖: Singleton類,定義了一個GetInst

Java 設計模式系列模式

重要 理解 iat 版本 ide 默認 ces 內部實現 成功 Java 設計模式系列(五)單例模式 單例模式確保某個類只有一個實例,而且自行實例化並向整個系統提供這個實例。 一、懶漢式單例 /** * 懶漢式單例類.在第一次調用的時候實例化自己 * 1. 構造器私

跟著別人學設計模式-----模式詳解

    作者:zuoxiaolong8810(左瀟龍),轉載自:http://www.cnblogs.com/zuoxiaolong/p/pattern2.html             上一章

常用的軟體設計模式模式

單例模式:即一個類只有一個例項,在類裡自己建立自己的例項。 優點: (1)單例模式會阻止其他物件例項化其自己的單例物件的副本,從而確保所有物件都訪問唯一例項。 (2)因為類控制了例項化過程,所以類可以靈活更改例項化過程。尤其是在C++中,每次new都要delete,而是用單例模式可以避免

設計模式5模式

模式介紹 單例模式是一種建立型設計模式,其中一個類只保證只有一個例項,該例項可以全域性訪問。 這意味著該模式強制特定物件不具有可訪問的建構函式,並且對該物件執行的任何訪問都是在該物件的同一例項上執行的。 示例 我們模擬一下餐館裡用於通知上菜鈴鐺,它在櫃檯上只有一個。 下面程式碼中syncRoot是為

設計模式模式詳解

愉快的開始自己的技術積累 ,設計模式中使用最普遍的單例模式開始; 設計模式中最為大家熟悉的必須是單例模式,專案中 必須 使用到的套路。首先陳述下我對 框架,模式的一些理解。   從學校出來,開始面試的時候張口框架,閉口模式,真的問道什麼是框架,我只能死鴨子嘴硬的強調 MVC ,

PHP設計模式——模式Singleton Pattern

PHP設計模式(一)——單例模式(Singleton Pattern) 單例模式(Singleton Pattern):顧名思義,就是隻有一個例項。作為物件的建立模式,單例模式確保某一個類只有一個例項,而且自行例項化並向整個系統提供這個例項。 (一)為

go 設計模式模式

go 的單例模式寫法比較簡單,可以通過sync.Once來輔助。 type Singleton struct { name string } var ( once sync.Once instance *Singleton ) func New()

設計模式php示例 模式和工廠模式

所謂的設計模式,就是具有多年開發經驗的人,在實際工作中為了解決某一種需求,而形成的一套程式碼方案。 1.單例模式: 單例模式:所謂的單例模式就是單一的例項。通過一個類永遠只能獲取一個物件。 基本的實現思路:單例模式要求類能夠有返回物件一個引用(永遠是同一個)和一個獲得該例項的方法(必