劍指offer-------單例模式
1.題目:
2.思路:
單例模式,是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。通過單例模式可以保證系統中,應用該模式的類一個類只有一個例項。即一個類只有一個物件例項。
單例模式是設計模式中最簡單的形式之一。這一模式的目的是使得類的一個物件成為系統中的唯一例項。要實現這一點,可以從客戶端對其進行例項化開始。因此需要用一種只允許生成物件類的唯一例項的機制,“阻止”所有想要生成物件的訪問。使用工廠方法來限制例項化過程。這個方法應該是靜態方法(類方法),因為讓類的例項去生成另一個唯一例項毫無意義。
對於系統中的某些類來說,只有一個例項很重要,例如,一個系統中可以存在多個列印任務,但是隻能有一個正在工作的任務;一個系統只能有一個視窗管理器或檔案系統;一個系統只能有一個計時工具或ID(序號)生成器。如在Windows中就只能開啟一個工作管理員。如果不使用機制對視窗物件進行唯一化,將彈出多個視窗,如果這些視窗顯示的內容完全一致,則是重複物件,浪費記憶體資源;如果這些視窗顯示的內容不一致,則意味著在某一瞬間系統有多個狀態,與實際不符,也會給使用者帶來誤解,不知道哪一個才是真實的狀態。因此有時確保系統中某個物件的唯一性即一個類只能有一個例項非常重要。
要點:
顯然單例模式的要點有三個;一是某個類只能有一個例項;二是它必須自行建立這個例項;三是它必須自行向整個系統提供這個例項。
從具體實現角度來說,就是以下三點:一是單例模式的類只提供私有的建構函式,二是類定義中含有一個該類的靜態私有物件,三是該類提供了一個靜態的公有的函式用於建立或獲取它本身的靜態私有物件。
優點
一、例項控制
單例模式會阻止其他物件例項化其自己的單例物件的副本,從而確保所有物件都訪問唯一例項。
二、靈活性
因為類控制了例項化過程,所以類可以靈活更改例項化過程。
缺點
一、開銷
雖然數量很少,但如果每次物件請求引用時都要檢查是否存在類的例項,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題。
二、可能的開發混淆
使用單例物件(尤其在類庫中定義的物件)時,開發人員必須記住自己不能使用new關鍵字例項化物件。因為可能無法訪問庫原始碼,因此應用程式開發人員可能會意外發現自己無法直接例項化此類。
三、物件生存期
不能解決刪除單個物件的問題。在提供記憶體管理的語言中(例如基於.NET Framework的語言),只有單例類能夠導致例項被取消分配,因為它包含對該例項的私有引用。在某些語言中(如 C++),其他類可以刪除物件例項,但這樣會導致單例類中出現懸浮引用。
3.程式碼:
(1)
public sealed class Singleton1 { //私有建構函式 private Singleton1() { } //靜態私有物件 private static Singleton1 instance = NULL; //該類提供了一個靜態的公有的函式用於建立或獲取它本身的靜態私有物件 public static Singleton1 Instance { get { if(instance == NULL) instance = new Singleton1(); return instance; } } }
(2)
public sealed class Singleton2
{
private Singleton2()
{
}
//鎖
private static readonly object syncObj = new object();
private static Singleton2 instance = NULL;
public static Singleton2 Instance
{
get
{
lock(syncObj)
{
if(instance == NULL)
instance = new Singleton2();
}
return instance;
}
}
}
(3)
public sealed class Singleton3
{
private Singleton3()
{
}
//鎖
private static readonly object syncObj = new object();
private static Singleton3 instance = NULL;
public static Singleton3 Instance
{
get
{
if(instance == NULL)
{
lock(syncObj)
{
if(instance == NULL)
instance = new Singleton3();
}
}
return instance;
}
}
}
(4)
public sealed class Singleton4
{
private Singleton4()
{
}
private static Singleton4 instance = NULL;
public static Singleton4 Instance
{
get
{
return instance;
}
}
}
(5)
public sealed class Singleton5
{
private Singleton5()
{
}
public static Singleton5 Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
static Nested()
{
}
instance static readonly Singleton5 instance = new Singleton5();
}
}
public class Singleton6 {
/*
*當第一次載入Singleton類時並不會初始化SINGLRTON,只有第一次呼叫getInstance方法的時候才會初始化SINGLETON
*第一次呼叫getInstance 方法的時候虛擬機器才會載入SingletonHoder類,這種方式不僅能夠保證執行緒安全,也能夠保證物件的唯一,
*還延遲了單例的例項化,所有推薦使用這種方式
* */
private Singleton6() {
}
public Singleton6 getInstance() {
return SingletonHolder.SINGLETON;
}
private static class SingletonHolder {
private static final Singleton6 SINGLETON = new Singleton6();
}
}