標籤:
轉載自互連網。
單例模式概述
下面我們來類比實現Windows工作管理員,假設工作管理員的類名為TaskManager,在TaskManager類中包含了大量的成員方法,例如建構函式TaskManager(),顯示進程的方法displayProcesses(),顯示服務的方法displayServices()等,該類的示意代碼如下:
|
class TaskManager
{
public TaskManager() {……} //初始化視窗
public void displayProcesses() {……} //顯示進程
public void displayServices() {……} //顯示服務
……
} |
為了實現Windows工作管理員的唯一性,我們通過如下三步來對上類進行重構:
(1)由於每次使用new關鍵字來執行個體化TaskManager類時都將產生一個新對象,為了確保TaskManager執行個體的唯一性,我們需要禁止類的外部直接使用new來建立對象,因此需要將TaskManager的建構函式的可見度改為private,如下代碼所示:
|
private TaskManager() {……} |
(2)將建構函式改為private修飾後該如何建立對象呢?不要著急,雖然類的外部無法再使用new來建立對象,但是在TaskManager的內部還是可以建立的,可見度只對類外有效。因此,我們可以在TaskManager中建立並儲存這個唯一執行個體。為了讓外界可以訪問這個唯一執行個體,需要在TaskManager中定義一個靜態TaskManager類型的私人成員變數,如下代碼所示:
|
private static TaskManager tm = null; |
(3)為了保證成員變數的封裝性,我們將TaskManager類型的tm對象的可見度設定為private,但外界該如何使用該成員變數並何時執行個體化該成員變數呢?答案是增加一個公有的靜態方法,如下代碼所示:
|
public static TaskManager getInstance()
{
if (tm == null)
{
tm = new TaskManager();
}
return tm;
} |
在getInstance()方法中首先判斷tm對象是否存在,如果不存在(即tm == null),則使用new關鍵字建立一個新的TaskManager類型的tm對象,再返回新建立的tm對象;否則直接返回已有的tm對象。
需要注意的是getInstance()方法的修飾符,首先它應該是一個public方法,以便供外界其他對象使用,其次它使用了static關鍵字,即它是一個靜態方法,在類外可以直接通過類名來訪問,而無須建立TaskManager對象,事實上在類外也無法建立TaskManager對象,因為建構函式是私人的。
|
|
思考
為什麼要將成員變數tm定義為靜態變數?
因為getInstance()只能訪問靜態變數。 |
|
通過以上三個步驟,我們完成了一個最簡單的單例類的設計,其完整代碼如下:
|
class TaskManager
{
private static TaskManager tm = null;
private TaskManager() {……} //初始化視窗
public void displayProcesses() {……} //顯示進程
public void displayServices() {……} //顯示服務
public static TaskManager getInstance()
{
if (tm == null)
{
tm = new TaskManager();
}
return tm;
}
……
} |
在類外我們無法直接建立新的TaskManager對象,但可以通過代碼TaskManager.getInstance()來訪問執行個體對象,第一次調用getInstance()方法時將建立唯一執行個體,再次調用時將返回第一次建立的執行個體,從而確保執行個體對象的唯一性。
上述代碼也是單例模式的一種最典型實現方式,有了以上基礎,理解單例模式的定義和結構就非常容易了。單例模式定義如下:
|
單例模式(Singleton Pattern):確保某一個類只有一個執行個體,而且自行執行個體化並向整個系統提供這個執行個體,這個類稱為單例類,它提供全域訪問的方法。單例模式是一種對象建立型模式。 |
單例模式有三個要點:一是某個類只能有一個執行個體;二是它必須自行建立這個執行個體;三是它必須自行向整個系統提供這個執行個體。
單例模式是結構最簡單的設計模式一,在它的核心結構中只包含一個被稱為單例類的特殊類。單例模式結構3-2所示:
單例模式結構圖中只包含一個單例角色:
● Singleton(單例):在單例類的內部實現只產生一個執行個體,同時它提供一個靜態getInstance()Factory 方法,讓客戶可以訪問它的唯一執行個體;為了防止在外部對其執行個體化,將其建構函式設計為私人;在單例類內部定義了一個Singleton類型的靜態對象,作為外部共用的唯一執行個體。
單例模式