程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 再談PHP單例模式Singleton

再談PHP單例模式Singleton

編輯:關於PHP編程

單例模式屬於創建型模式,它是設計模式中最簡單的一種模式,當然它的使用也是無處不在的。

單例模式保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

當需要控制一個類的實例數量,且調用者可以從一個公共的眾所周知的訪問點訪問時,我們就可以考慮使用單例模式了。

我們用 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;
    }
}

由此看來,實現單例模式我們可以做下列幾步:

  1. 在類中創建一個靜態變量,變量類型為當前類;
  2. 在類中創建一個公共的靜態方法,讓用戶可以通過此方法創建此類的靜態對象;
  3. 最後將構造函數設置為 protected 或者 private。

Program List:最簡單的單例類

<?php
class Fruit
{
    static private $_color;
    private function __construct()
    {
    }
	
    static public function singleton() {
        return isset(self::$_color) ? self::$_color : self::$_color = new self();
    }
}
?>

Program List:可擴展的單例類

一個可擴展的單例類看似不可能,但下面的程序很接近這種效果。

    
<?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)

Program List:單例類與其派生類

  
<?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.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved