面向對象編程中有這種情況,希望類只有一個實例且夠成其他類的成員屬性,這樣如果直接作爲全局變量在頁面的前面定義類的實例,在其他類中當屬性使用,這中做法破壞了oop的封裝性,並且如果使用不當會導致命名衝突。而單例模式的設計就是專門爲了解決這類問題的。
顧名思義單例就是單個實例,那麼這個類必須有一定的規範:構造方法私有 靜態私有屬性(本類的實例) 公開的靜態方法(該方法爲了判斷該實例是否存在,如果不在則創建。然後返回該實例)。
另外,需要創建__clone()方法防止對象被複制(克隆)
第一種方法:設置魔術方法__clone();訪問權限爲private
第二種方法:若__clone()爲公用方法,則在函數中加上自定義錯誤,如trigger_error('Clone is not allow!',E_USER_ERROR);
爲什麼要使用PHP單例模式?
1、php的應用主要在於數據庫應用, 所以一個應用中會存在大量的數據庫操作, 使用單例模式, 則可以避免大量的new 操作消耗的資源。
2、如果系統中需要有一個類來全局控制某些配置信息, 那麼使用單例模式可以很方便的實現. 這個可以參看ZF的FrontController部分。
3、在一次頁面請求中, 便於進行調試, 因爲所有的代碼(例如數據庫操作類db)都集中在一個類中, 我們可以在類中設置鉤子, 輸出日誌,從而避免到處var_dump, echo。
在PHP中,所有的變量無論是全局變量還是類的靜態成員,都是頁面級的,每次頁面被執行時,都會重新建立新的對象,都會在頁面執行完畢後被清空,這樣似乎PHP單例模式就沒有什麼意義了,所以PHP單例模式我覺得只是針對單次頁面級請求時出現多個應用場景並需要共享同一對象資源時是非常有意義的。
example:
class mysqlink {private $host;
private $user;
private $pwd;
private $db;
private $charset;
private $mysqli;
static private $instance;
static public function getInstance(){
if(empty(self::$instance)){
$host = "localhost";
$user = "root";
$DBpwd = "911004";
$db = "box";
$charset = "gbk";
self::$instance=new mysqlink($host, $user, $DBpwd, $db, $charset);
}
return self::$instance;
}
private function __clone(){//限制單例模式的克隆
}
private function __construct($host, $user, $pwd, $db, $charset) {
$this->host = $host;
$this->user = $user;
$this->pwd = $pwd;
$this->db = $db;
$this->charset = $charset;
$this->mysqli = new mysqli("$host", "$user", "$pwd", "$this->db");
if (mysqli_connect_error()) {
die('Connect Error (' . mysqli_connect_errno . ') ' . mysqli_connect_error);
}
if (!$this->mysqli->set_charset($this->charset)) { //設置客戶端編碼
printf("Error loading character set $this->charset: %s\n", $this->mysqli->error);
}
}
}