博主最近開始真正的潛心學習PHP的各種設計模式。剛開始當然從一些簡單的設計模式開始學起,比如之前發表的工廠模式,今天的單利模式,還有之後要看的注冊模式。其實這些都是比較基礎的設計模式,一些簡單的示例一看就能明白,對於稍加復雜些的示例,花點心思進去也能夠理解。可重點是,光是知道了解這麼個東西是不夠的,而是如何能夠把他更好的運用的項目中去,在實踐中增加熟練度。好吧,還是說說今天要看的單例模式吧。
一、什麼是單例模式?
1、含義:
作為對象的創建模式,單例模式確保某一個類只有一個實例,而且自行實例化並向整個系統全局地提供這個實例。它不會創建實例副本,而是會向單例類內部存儲的實例返回一個引用。
2、單例模式的三個要點:
(1)需要一個保存類的唯一實例的靜態成員變量。
(2)構造函數和克隆函數必須聲明為私有的,防止外部程序new類從而失去單例模式的意義。
(3)必須提供一個訪問這個實例的公共的靜態方法(通常為getInstance方法),從而返回唯一實例的一個引用。
假設我們目前需要設計一個數據庫訪問類,需要用到單例模式,看如下示例:
<?php class DB { private $_db; private static $_instance; private function __construct(...) { $this->_db = pg_connect(...);//postgrsql } private function __clone() {}; //覆蓋__clone()方法,禁止克隆 public static function getInstance() { if(!(self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; } public function sql(...) { /* * code */ } } $db = DB::getInstance(); $db->sql(); ?>
<111?111php111
/1**
* 設計模式之單例模式
* $_instance必須聲明為靜態的私有變量
* 構造函數和析構函數必須聲明為私有,防止外部程序new
* 類從而失去單例模式的意義
* getInstance()方法必須設置為公有的,必須調用此方法
* 以返回實例的一個引用
* ::操作符只能訪問靜態變量和靜態函數
* new對象都會消耗內存
* 使用場景:最常用的地方是數據庫連接。
* 使用單例模式生成一個對象後,
* 該對象可以被其它眾多對象所使用。
*/
class Danli {
//保存類實例的靜態成員變量
private static $_instance;
//private標記的構造方法
private function __construct(){
echo 'This is a Constructed method;';
}
//創建__clone方法防止對象被復制克隆
public function __clone(){
trigger_error('Clone is not allow!',E_USER_ERROR);
}
//單例方法,用於訪問實例的公共的靜態方法
public static function getInstance(){
if(!(self::$_instance instanceof self)){
self::$_instance = new self;
}
return self::$_instance;
}
public function test(){
echo '調用方法成功';
}
}
//用new實例化private標記構造函數的類會報錯
//$danli = new Danli();
//正確方法,用雙冒號::操作符訪問靜態方法獲取實例
$danli = Danli::getInstance();
$danli->test();
//復制(克隆)對象將導致一個E_USER_ERROR
$danli_clone = clone $danli;
例子3
1、普通的數據庫訪問例子:
<?php ...... //初始化一個數據庫句柄 $db = new DB(...); //添加用戶信息 $db->addUserInfo(...); ...... //在函數中訪問數據庫,查找用戶信息 function getUserInfo() { $db = new DB(...);//再次new 數據庫類,和數據庫建立連接 $db = query(....);//根據查詢語句訪問數據庫 } ?>
例子4、應用單例模式對數據庫進行操作:
<?php class DB { private $_db; private static $_instance; private function __construct(...) { $this->_db = pg_connect(...);//postgrsql } private function __clone() {}; //覆蓋__clone()方法,禁止克隆 public static function getInstance() { if(! (self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; } public function addUserInfo(...) { } public function getUserInfo(...) { } } //test $db = DB::getInstance(); $db->addUserInfo(...); $db->getUserInfo(...); ?>
二、為什麼要使用單例模式?
1、PHP缺點:
PHP語言是一種解釋型的腳本語言,這種運行機制使得每個PHP頁面被解釋執行後,所有的相關資源都會被回收。也就是說,PHP在語言級別上沒有辦法讓某個對象常駐內存,這和asp.net、Java等編譯型是不同的,比如在Java中單例會一直存在於整個應用程序的生命周期裡,變量是跨頁面級的,真正可以做到這個實例在應用程序生命周期中的唯一性。然而在PHP中,所有的變量無論是全局變量還是類的靜態成員,都是頁面級的,每次頁面被執行時,都會重新建立新的對象,都會在頁面執行完畢後被清空,這樣似乎PHP單例模式就沒有什麼意義了,所以PHP單例模式我覺得只是針對單次頁面級請求時出現多個應用場景並需要共享同一對象資源時是非常有意義的。
2、單例模式在PHP中的應用場合:
(1)應用程序與數據庫交互
一個應用中會存在大量的數據庫操作,比如過數據庫句柄來連接數據庫這一行為,使用單例模式可以避免大量的new操作,因為每一次new操作都會消耗內存資源和系統資源。
(2)控制配置信息
如果系統中需要有一個類來全局控制某些配置信息, 那麼使用單例模式可以很方便的實現.