幾乎所有面向對象的程序中,總有一些類的對象需要是唯一的,例如,通過數據庫句柄到數據庫的連接是獨占的。您希望在應用程序中共享數據庫句柄,因為在保持連接打開或關閉時,它是一種開銷。再如大家最經常用的IM,如QQ,在同一臺電腦,一個帳號只能有唯一的登錄。
1. 問題
怎樣確保一個特殊類的實例是獨一無二的(它是這個類的唯一實例),并且這個實例易于被訪問呢?
2. 解決方案
1)全局變量:一個全局變量使得一個對象可以被訪問,但它不能防止你實例化多個對象。因為你的任何代碼都能修改全局變量,這將不可避免的引起更多調試的意外。換句話說,全局變量的狀態總是會出現一些問題的。
2)類構造函數私有和類自身的靜態方法:讓類自身負責保存它的唯一實例(靜態變量)。這個類可以保證沒有其他實例可以被創建(通過截取創建新對象的請求) ,并且它可以提供一個訪問該實例的方法(靜態方法)。這就是Singleton模式。
3. 適用性
在下面的情況下可以使用單件模式
1)當類只能有一個實例而且客戶可以從一個眾所周知的訪問點訪問它時。
2)當這個唯一實例應該是通過子類化可擴展的,并且客戶應該無需更改代碼就能使用一個擴展的實例時。
4. 實現:
UML結構:
代碼:
<?php class Singleton { static private $_instance = null;//靜態成員保存唯一實例 /** * 私有構造函數,保證不能被外部訪問 * */ private function __construct() {} /** * 靜態方法將創建這個實例的操作并保證只有一個實例被創建 * * @return unknown */ public static function getInstance() { if (!self::$_instance) { self::$_instance = new self(); } return self::$_instance; } }
5. 效果
Singleton模式有許多優點:
1) 對唯一實例的受控訪問, 因為Singleton類封裝它的唯一實例,所以它可以嚴格的控制客戶怎樣以及何時訪問它。
2) 縮小名空間,Singleton模式是對全局變量的一種改進。它避免了那些存儲唯一實例的全局變量污染名空間。
3) 允許對操作和表示的精化Singleton類可以有子類,而且用這個擴展類的實例來配置一個應用是很容易的。你可以用你所需要的類的實例在運行時刻配置應用。
4) 允許可變數目的實例 這個模式使得你易于改變你的想法,并允許Singleton類的多個實例。此外,你可以用相同的方法來控 制應用所使用的實例的數目。只有允許訪問 Singleton實例的操作需要改變。
6 .單件模式可以多個實例
單件模式并不是說一個類只能只有一個實例。假設我們使用在一個web 請求或者進程里面。一個用戶id對應的某個類只能有唯一的實例。在下面的例子中,我們的User類,可以有多個實例,每個實例對應一個uid. 實例列表注冊到靜態變量$_instance并和uid關聯起來。最簡單的例子是我們前面提到的QQ,在同一臺電腦,可以使用多帳號登錄, 但一個帳號只能有唯一的登錄.
代碼:
<?php class User { static private $_instance = array();//靜態成員保存唯一實例 private $_uid ; /** * 私有構造函數,保證不能被外部訪問 * */ private function __construct($uid ) { $this->_uid = $uid; } /** * 靜態方法將創建這個實例的操作并保證只有一個實例被創建 * * @return unknown */ public static function getInstance($uid = 0) { if (!self::$_instance || !isset(self::$_instance[$uid]) ) { self::$_instance[$uid] = new self($uid); } return self::$_instance[$uid]; } }
在zend framework中的Zend_Controller_Front前端控制器,就是采用單價模式來設計的:
Zend_Controller_Front是Zend_Controller_Controller體系的組織者,它是FrontController設計模式的實現。
Zend_Controller_Front處理服務器接受的所有請求,并最后負責將請求分配給ActionController(Zend_Controller_Action)
$frontController = Zend_Controller_Front::getInstance(); $frontController->addModuleDirectory( “參數”); $frontController->dispatch();
轉自:http://blog.csdn.net/hguisu/article/details/7515416
原創文章,作者:s19930811,如若轉載,請注明出處:http://www.www58058.com/2949