單例模式屬於創建型模式,它是設計模式中最簡單的一種模式,當然它的使用也是無處不在的。
單例模式保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
當需要控制一個類的實例數量,且調用者可以從一個公共的眾所周知的訪問點訪問時,我們就可以考慮使用單例模式了。
我們用 UML 來設計單例模式,當然在以後的設計模式的設計部分,我們都將采用 UML 來描述我們的設計,這樣就更為形象化了。
從 UML 設計圖中我們可以看出,為了讓一個類只有一個實例,它必須創建一個靜態變量,然後我們用一個公共靜態的 Instance() 的方法來創建它,但是為了避免這個類自身的構造函數可以創建對象,我們將構造函數設置成 protected 或者 private,這樣外部就只能通過 Instance() 的方法來創建一個靜態的 Singleton 類。看來這樣我們達到了我們的目的,接下來我們看代碼:
public class Singleton {
private static Singleton instance;
protected Singleton()
public static Singleton Instance() {
if(instance != null) instance = new Singleton();
return instance;
}
}
由此看來,實現單例模式我們可以做下列幾步:
<?php
class Fruit
{
static private $_color;
private function __construct()
{
}
static public function singleton() {
return isset(self::$_color) ? self::$_color : self::$_color = new self();
}
}
?>
一個可擴展的單例類看似不可能,但下面的程序很接近這種效果。
<?php
class Test extends Fruit {
public static function getInstance()
{
return Fruit::getSingleton(get_class());
}
}
?>
<?php
class Fruit {
/***********************
* HOW TO USE
*
* Inherit(extend) from Singleton and add getter:
*
* //public getter for singleton instance
* public static function getInstance(){
* return Singleton::getSingleton(get_class());
* }
*
*/
private static $instanceMap = array();
//protected getter for singleton instances
protected static function getSingleton($className)
{
if(!isset(self::$instanceMap[$className]))
{
$object = new $className;
//Make sure this object inherit from Singleton
if($object instanceof Fruit)
{
self::$instanceMap[$className] = $object;
}
else
{
throw SingletonException("Class '$className' do not inherit from Singleton!");
}
}
return self::$instanceMap[$className];
}
//protected constructor to prevent outside instantiation
protected function __construct(){
}
//denie cloning of singleton objects
public final function __clone(){
trigger_error('It is impossible to clone singleton', E_USER_ERROR);
}
}
?>
<?php
class Apple extends Fruit {
protected $rndId;
protected function __construct(){
$this->rndId = rand();
}
public function whatAmI(){
echo 'I am a Apple('.$this->rndId.')<br />';
}
public static function getInstance(){
return Fruit::getSingleton(get_class());
}
}
class GreenApple extends Apple {
public function whatAmI(){
echo 'I am a GreenApple('.$this->rndId.')<br />';
}
public static function getInstance(){
return Fruit::getSingleton(get_class());
}
}
$apple1 = Apple::getInstance();
$apple2 = GreenApple::getInstance();
$apple1->whatAmI();// should echo 'I am a A(some number)
$apple2->whatAmI();// should echo 'I am a B(some number)
$apple1 = Apple::getInstance();
$apple2 = GreenApple::getInstance();
$apple1->whatAmI();// should echo 'I am a A(same number as above)
$apple2->whatAmI();// should echo 'I am a B(same number as above)
// $a = new A();// this should fail
// $b = new B();// this should fail
?>
程序運行結果:
I am a Apple(4462) I am a GreenApple(8207) I am a Apple(4462) I am a GreenApple(8207)
<?php
class Fruit
{
// Hold an instance of the class
private static $instance;
// A private constructor; prevents direct creation of object
protected function __construct()
{
echo 'I am constructed';
}
// The singleton method
public static function singleton($classname = __CLASS__)
{
if (!isset(self::$instance)) {
self::$instance = new $classname;
}
return self::$instance;
}
}
class Apple extends Fruit {
public static function singleton()
{
return parent::singleton(__CLASS__); // NOTE The singleton method MUST return an instance.
}
public function showColor()
{
echo 'My Color is Red.';
}
}
$subclassInstance = Apple::singleton();
$subclassInstance->showColor();
?>
程序運行結果:
I am constructed My Color is Red.