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

PHP職責模式單例模式

編輯:關於PHP編程

模式對於面向對象開發是相當重要的。一種模式可以幫助我們創建能夠實現特定任務的對象,成為類的職責。模式還允許我們修改某個類,但不需要修改與這個類有關系的代碼,這個稱為類的多態。

單例模式又稱為職責模式,它用來在應用程序中創建一個單一的功能訪問點。下面我們來探討並且結結實實地掌握單例的思想還有應用。

在復雜的系統中,使用單例模式在維持應用程序狀態的同步方面尤其有用。所有的單例類至少擁有以下三個元素:

  • 一個標記為private的構造函數。
  • 保存類的實例的靜態成員變量。
  • 訪問這個實例的公共靜態方法。

Program List:單例模式的類

<?php
class Fruit
{
    // Hold an instance of the class
    private static $instance;
    
    // A private constructor; prevents direct creation of object
    // 防止類被當作實例使用,就是無法使用此類創建對象
    private function __construct() 
    {
        echo 'I am constructed';
    }
    // The singleton method
    public static function singleton() 
    {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }
        return self::$instance;
    }
    
    // Example method
    public function showColor()
    {
        echo 'My color is !';
    }
    // Prevent users to clone the instance
    public function __clone()
    {
        trigger_error('Clone is not allowed.', E_USER_ERROR);
    }
}
// This would fail because the constructor is private
//$test = new Fruit();
// This will always retrieve a single instance of the class
$test = Fruit::singleton();
echo '<br />';
$test->showColor();
// This will issue an E_USER_ERROR.
//$test_clone = clone $test;
?>

程序運行結果:

I am constructed
My color is !

從這個程序可以看出一些特別的東西。和普通的類不同,單例類是不能直接實例化的,它只能被自身實例化。要獲得這種效果,__construct()方法必須被標記為private。如果試圖用private構造函數構造一個對象,就會得到一個訪問性級別的錯誤。

那麼單例類如何起作用呢?單例類就是要向其它類提供一個實例,用它調用各種方法。單例類回通過內部存儲的實例返回一個引用,所以單例類不會重復占用內存和系統資源,從而讓應用程序的其它部分更好的使用資源。所以,你的數據庫訪問最好使用單例模式構建,那麼就不會創建太多的數據庫連接實例,從而讓你的系統跑得更快。

一個空的__clone()方法很有必要,它可以防止對象被復制或者克隆。

self::$instance 可以檢測到類是否已經被初始化。如果保存實例的靜態成員為空或者還不是類自身的一個實例,那麼這個實例將會被創建並保存到存放實例的變量中。

Program List:無private構造函數的單例

一個不嚴格的單例,沒有private構造函數,也沒有本身的引用。不知道還算不算模式了。

  
<?php
class Fruit {
  	public static $height = 2;
  	public static $weight = 2;
  	public static function getInstance() {
    	return new Fruit();
  	}
  	public function getHeight() {
    	return self::$height;
  	}
  	public function getWeight() {
    	return self::$weight;
  	}
  	public function setHeight($value) {
    	if($value > 0 && $value < 100) self::$height = $value;
  	}
  	public function setWeight($value) {
    	if($value > 0 && $value < 100) self::$weight = $value;
  	}
  	public function __toString() {
    	return 'Fruit[height=' . self::$height . ', weight=' . self::$weight . ']';
  	}
}
// try to set data before any objects is created
Fruit::$height = 55;
$msm1 = Fruit::getInstance();  // use the getInstance() method
$msm2 = new Fruit();           // use the default constructor
$msm2->setWeight(78);                           // set data with an instantiated object
echo $msm1 . '<br />';
echo $msm2 . '<br />';
echo Fruit::getInstance() . '<br>';
echo (new Fruit());
?>

程序運行結果:

Fruit[height=55, weight=78]
Fruit[height=55, weight=78]
Fruit[height=55, weight=78]
Fruit[height=55, weight=78]

Program List:數據庫連接職責

<?php
	class Database {
		private $_db;
		static $_instance;
		
		private function __construct() {
			$this->_db = pg_connect('dbname=example_db');
		}
		
		private __clone() {};
		
		public static function getInstance() {
			if( ! (self::$_instance instanceof self) )
			{
				self::$_instance = new self();
			}
			return self::$_instance;
		}
		
		public function query($sql)
		{
			return pg_query($this->_db,$sql);
		}
	}
?>

如何使用這個單例類?

$db = Database::getInstance();
$db->query('SELECT * FROM example_table');

也就是獲取對象的方法有些區別而已,使用起來與其它對象沒有特別之處。

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