單例模式
單例模式顧名思義,就是隻有一個實例。作為對象的創建模式[GOF95],單例模式确保某一個類隻有一個實例,而且自行實例化并向整個系統提供這個實例。這個類稱為單例類。
簡介
Singleton的靜态結構圖單例模式是設計模式中最簡單的形式之一。這一模式的目的是使得類的一個對象成為系統中的唯一實例。要實現這一點,可以從客戶端對其進行實例化開始。因此需要用一種隻允許生成對象類的唯一實例的機制,“阻止”所有想要生成對象的訪問。使用工廠方法來限制實例化過程。這個方法應該是靜态方法(類方法),因為讓類的實例去生成另一個唯一實例毫無意義。
Static uniqueInstance是singleton的唯一實例,static sharedInstance将把它返回客戶端。通常,sharedInstance會檢查uniqueInstance是否已經被實例化。如果沒有,它會生成一個實例然後返回uniqueInstance。
動機
對于系統中的某些類來說,隻有一個實例很重要,例如,一個系統中可以存在多個打印任務,但是隻能有一個正在工作的任務;一個系統隻能有一個窗口管理器或文件系統;一個系統隻能有一個計時工具或ID(序号)生成器。如在Windows中就隻能打開一個任務管理器。如果不使用機制對窗口對象進行唯一化,将彈出多個窗口,如果這些窗口顯示的内容完全一緻,則是重複對象,浪費内存資源;如果這些窗口顯示的内容不一緻,則意味着在某一瞬間系統有多個狀态,與實際不符,也會給用戶帶來誤解,不知道哪一個才是真實的狀态。因此有時确保系統中某個對象的唯一性即一個類隻能有一個實例非常重要。
如何保證一個類隻有一個實例并且這個實例易于被訪問呢?定義一個全局變量可以确保對象随時都可以被訪問,但不能防止我們實例化多個對象。一個更好的解決辦法是讓類自身負責保存它的唯一實例。這個類可以保證沒有其他實例被創建,并且它可以提供一個訪問該實例的方法。這就是單例模式的模式動機。
單例模式的要點
顯然單例模式的要點有三個;一是某個類隻能有一個實例;二是它必須自行創建這個實例;三是它必須自行向整個系統提供這個實例。在下面的對象圖中,有一個"單例對象",而"客戶甲"、"客戶乙"和"客戶丙"是單例對象的三個客戶對象。可以看到,所有的客戶對象共享一個單例對象。而且從單例對象到自身的連接線可以看出,單例對象持有對自己的引用。
一些資源管理器常常設計成單例模式。
在計算機系統中,需要管理的資源包括軟件外部資源,譬如每台計算機可以有若幹個打印機,但隻能有一個Printer spooler,以避免兩個打印作業同時輸出到打印機中。每台計算機可以有若幹傳真卡,但是隻應該有一個軟件負責管理傳真卡,以避免出現兩份傳真作業同時傳到傳真卡中的情況。每台計算機可以有若幹通信端口,系統應當集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調用。
需要管理的資源包括軟件内部資源,譬如,大多數的軟件都有一個(甚至多個)屬性(properties)文件存放系統配置。這樣的系統應當由一個對象來管理一個屬性文件。
需要管理的軟件内部資源也包括譬如負責記錄網站來訪人數的部件,記錄軟件系統内部事件、出錯信息的部件,或是對系統的表現進行檢查的部件等。這些部件都必須集中管理,不可政出多頭。
優缺點
優點
一、實例控制
單例模式會阻止其他對象實例化其自己的單例對象的副本,從而确保所有對象都訪問唯一實例。
二、靈活性
因為類控制了實例化過程,所以類可以靈活更改實例化過程。
缺點
一、開銷
雖然數量很少,但如果每次對象請求引用時都要檢查是否存在類的實例,将仍然需要一些開銷。可以通過使用靜态初始化解決此問題。
二、可能的開發混淆
使用單例對象(尤其在類庫中定義的對象)時,開發人員必須記住自己不能使用new關鍵字實例化對象。因為可能無法訪問庫源代碼,因此應用程序開發人員可能會意外發現自己無法直接實例化此類。
三、對象生存期
不能解決删除單個對象的問題。在提供内存管理的語言中(例如基于.NET Framework的語言),隻有單例類能夠導緻實例被取消分配,因為它包含對該實例的私有引用。在某些語言中(如C++),其他類可以删除對象實例,但這樣會導緻單例類中出現懸浮引用。



















