軟體設計模式修煉 單例模式

2022-01-10 06:51:08 字數 2998 閱讀 9628

通過單例模式可以保證系統中乙個類只有乙個例項而且該例項易於被外界訪問,從而方便對例項個數的控制並節約系統資源。如果希望在系統中某個類的物件只能存在乙個,單例模式是最好的解決辦法。

對系統中某些類來說,只有乙個例項很重要,例如,乙個系統只能有乙個視窗管理器或檔案系統。因此確保系統中某個物件的唯一性即乙個類只能有乙個例項很重要。

單例模式確保某乙個類只有乙個例項,而且自行例項化並向整個系統提供這個例項,這個類稱為單例類,它提供全域性訪問方法。單例模式有三個要點:一是某個類只能有乙個例項;二是它必須自行建立這個例項;三是它必須自行向整個系統提供這個例項。

單例模式的目的是保證類僅有乙個例項,並提供乙個訪問它的全域性訪問點。單例類擁有乙個私有建構函式,確保使用者無法通過new關鍵字直接例項化。除此之外,該模式包含乙個靜態私有成員變數與靜態公有的工廠方法,該工廠方法負責校驗例項存在性並例項化自己,然後儲存在靜態成員變數中,以確保只有乙個例項被建立。因此在單例模式的實現過程中要注意三點:

單例類的建構函式為私有

提供乙個自身的靜態私有成員變數

提供乙個公有的靜態工廠方法

public class singleton 

//靜態公有工廠方法,返回唯一例項

public static singleton getinstance()

return instance;

}}

public class client 

}

單例模式優點如下:

提供對外唯一例項的受控訪問

由於在系統記憶體中只存在乙個物件,因此可以節約系統資源

允許可變數目的例項,基於單例模式我們可以進行擴充套件,使用與單例模式相似的方法來獲得指定個數的物件例項

單例模式缺點如下:

由於單例模式中沒有抽象層,因此單例類的擴充套件有很大困難

單例類的職責過重,一定程度上違背了單一職責原則

如果例項化的物件長時間不被利用,系統會認為它是垃圾,會自動銷毀並**資源,下次利用時又將重新例項化,將導致物件狀態的丟失

在以下情況可以適用單例模式:

系統只需要乙個例項物件,或者需要考慮資源消耗太大而只允許建立乙個物件

客戶呼叫類的單個例項只允許乙個公共訪問點,除了該公共訪問點,不能通過其他途徑訪問該例項

使用單例模式有乙個必要條件:在乙個系統中要求乙個類只有乙個例項時才應當使用單例模式。反過來,如果乙個類可以有幾個例項共存,就需要對單例模式進行改進,使之成為多例模式。在使用過程中我們還需注意以下兩個問題:

不要使用單例模式訪問全域性變數,因為這違背了單例模式的用意

不要將資料庫連線做成單例,因為乙個系統可能會與資料庫有多個連線,否則可能造成資源無法及時釋放

在定義靜態變數的時候例項化單例類,在類載入的時候就已經建立了單例物件。在這個類被載入時,靜態變數 instance 會被初始化,此時類的私有建構函式會被呼叫,單例類的唯一例項將被建立。

public class eagersingleton 

public static eagersingleton getinstance()

}

懶漢式單例類不是在定義靜態變數時例項化單例類,而是在呼叫靜態工廠方法時例項化單例類,因此在類載入時並沒有建立單例物件。

public class lazysingleton 

public static lazysingleton getinstance()

return instance;

}}

從資源利用效率角度來說,懶漢式單例模擬餓漢式單例類稍好。從速度和反應時間角度來說,餓漢式單例模擬懶漢式稍好。然而,懶漢式單例類在例項化時,必須處理好多個執行緒同時首次引用此類時的訪問限制問題,就上述的懶漢式單例類例項來說,是執行緒不安全的。為了實現執行緒安全,必須加鎖 synchronized 實現單例,但加鎖會影響效率。

public class lazysingleton 

public static synchronized lazysingleton getinstance()

return instance;

}}

由於 synchronized 具有排他性,同一時刻只有乙個執行緒進入到同步**塊或者同步方法之中,每次只能通過乙個執行緒,效率自然很低。採用雙鎖機制,在保證安全的前提下還能保持高效能。

public class lazysingleton 

public static lazysingleton getinstance() }}

return instance;

}}

其中變數 instance 還使用了 volatile 修飾,使用 volatile 的目的是防止指令重排序以及保證變數在多執行緒執行時的可見性。

這種方法不僅能確保執行緒安全,也能保證單例的唯一性,同時也延遲了單例的例項化。

public class singleton 

private singleton(){}

private static final singleton getinstance()

}

內部類(不論是靜態內部類還是非靜態內部類)都是在第一次使用時才會被載入,而且靜態內部類的載入不需要依附外部類,在使用時才載入,因此只有當呼叫 singletonholder.instance 這條語句時才會初始化 instance。

那麼會不會出現多個執行緒同時載入 singletonholder 類的情況呢?答案是不會。jvm 規定,如多個執行緒用到同乙個類,而這個類還未被載入,則只有乙個執行緒去載入類,其他執行緒等待。因此靜態內部類模式的單例可以保證執行緒安全。

列舉天然解決了多執行緒同步執行的問題,而且還自動支援序列化機制,防止反序列化重新建立新的物件,絕對防止多次例項化。

public enum singleton 

}

軟體設計模式 單例模式

單例模式,顧名思義,就是只能由乙個例項,那麼我們就必須保證 該類不能被複製。該類不能被公開的創造。那麼對於c 來說,他的建構函式,拷貝建構函式和他的賦值函式都不能被公開呼叫。但對於該私有的建構函式的構造時機上來說也可以分兩種情況來構造 只有當需要改類的時候去構造 即為懶漢模式 在程式開始之前我就先構...

軟體設計模式 單例模式

前篇 軟體設計模式 基礎 前篇 軟體設計模式 三種工廠模式 前篇 軟體設計模式 裝飾者模式 單例模式是建立型模式 2.單例模式的實現 3.例子 在實踐專案開發中經常會遇到一些物件,這樣的物件在全域性當中僅存在乙個就可以。如果出現多個。程式執行可能會失敗。或是記憶體上的管理問題。就是只需要乙個即可,比...

軟體設計模式之單例模式

保證乙個類僅有乙個例項,並提供乙個全域性訪問點 建立型想確保任何情況下都絕對只有乙個例項 在記憶體裡只有乙個例項,減少了記憶體開銷。可以避免對資源的多重占用。設定全域性訪問點,嚴格控制訪問。沒有介面,擴充套件困難 傳統懶漢模式 如下 public class lazysingleton public...