先簡單的介紹一下單例模式。單例模式就是在應用程序中保持某一個類實例只存在一個,而且不可以受外部環境的影響而生成這個類的第二個實例。它的優點,實際點見,如果在WEB開發中,保持單一個數據操作類實例的存在,可以減少不必要的多余連接數據庫資源的消耗,對於大型的軟件開發來說,可以使用單例來維持程序的狀態,使不同操作實現同步,因為單例一直占據內存,而從不會有副本。
而對於PHP,使用單例最常用的場合莫過於寫一個數據庫操作類。不過在PHP中實現單例,有以下規則:
1)單例類必須擁有一個現式聲明的構造函數,並且是私有的。
2)單例類必須有一個靜態變量來存儲類的實例,這樣可以保持這個單例類就只有那麼一個實例。
3)單例類必須提供一個靜態方法,供其他所有的對象應用這個單例。
為什麼要滿足以上三個條件呢:
1)因為單例類在整個應用程序運行時,只能被創造一次,而且這種創造是不是通過外部調用而完成,而是自身完成。所以單例類是自己實例化自己,所以其構造函數必須是私有。任何其他外部對象都不可以再次構造一個單例類的副本。
2)因為單例類只能夠自己實例化自己,而又要為所有外部應用提供自己的實例,所以類內部必須有一個可供外界訪問,而又是唯一不變的訪問存儲對象點,所以要提供一個靜態變量去存儲單例類自己實例化自己的那個實例對象。
3)因為單例類的構造函數是私有的,所以單例類必須提供一個外部接口供外部環境調用單例類,所以必須有一個靜態方法,它可以初始化單例類或者返回單例類的對象的引用。
一個簡單的例子:
代碼如下復制代碼classDB{
private$_link;
// 保持單例類的靜態變量
static$_instance;
// 私有的構造函數
privatefunction__construct(){
$this->_link = @mysqli_connect(__HOST__, __USER__, __PASSWORD__, __DATABASE__);
if(! ($this->_link)){
echo'Something wrong occurs on the database connection!'
}
}
// 防止單例類被克隆
privatefunction__clone(){}
// 外界訪問單例類實例的接口
publicstaticfunctiongetInstance(){
if(! (self::$_instanceinstanceofself)){
self::$_instance=newself();
}
returnself::$_instance;
}
}
注意,以上定義的一個 __clone() 函數,防止單例類對象被克隆。
以下也是一個簡單的數據庫操作類的單例,供參考:
代碼如下復制代碼classDB {
/**
* the database connection
* @var resource
* @access private
*/
private$_link;
/**
* the static instance of single db
* @var object
* @access static
*/
static$_instance;
/**
* construct the single object
* @return null
* @access private
*/
privatefunction__construct(){
$this->_link = @mysqli_connect(__HOST__, __USER__, __PASSWORD__, __DATABASE__);
if(! ($this->_link)){
echo'Something wrong occurs on the database connection!'
}
}
/**
* empty clone
* @return null
* @access private
*/
privatefunction__clone(){}
/**
* for other object to get the instance of db
* @return self::instance
* @access public
*/
publicstaticfunctiongetInstance(){
if(! (self::$_instanceinstanceofself)){
self::$_instance=newself();
}
returnself::$_instance;
}
/**
* query
* @param sql string
* @param message string
* @return resource
* @access public
*/
publicfunctionquery($sql,$message){
$result= @mysqli_query($this->$_link,$sql)ordie($message. mysqli_error($this->$_link));
return$result;
}
/**
* mysqli_num_rows
* @param result resource
* @return int
* @access public
*/
publicfunctionnum($result){
return@mysqli_num_rows($result);
}
/**
* mysqli_fetch_array
* @param result resource
* @return array
* @access public
*/
publicfunctionfetchArr($result){
return@mysqli_fetch_array($result);
}
/**
* mysqli_insert_id
* @return int
* @access public
*/
publicfunctionlast_id(){
return@mysqli_insert_id($this->_link);
}
/**
* close the database connection
* @param result resource
* @return null
* @access public
*/
publicfunctionclose(){
@mysqli_close($this->_link);
}
/**
* fetch once result from the specific sql query
* @param sql string
* @param message string
* @return array
* @access public
*/
publicfunctionfetchArrOnce($sql,$message){
$result=$this->query($sql,$message);
$row=$this->fetchArr($result);
return$row;
}
/**
* fetch all results from the specific sql query
* @param sql string
* @param message string
* @return array
* @access public
*/
publicfunctionfetchArrMore($sql,$message){
$result=$this->query($sql,$message);
$moreRow=array();
while($row=$this->fetchArr($result)){
$moreRow[] =$row;
}
return$moreRow;
}
/**
* fetch the number of results from the specific sql query
* @param sql string
* @param message string
* @return array
* @access public
*/
publicfunctionfetchNum($sql,$message){
$result=$this->query($sql,$message);
$resultNum=$this->num($result);
return$resultNum;
}
/**
* mysqli_prepare
* @param sql string
* @return stmt object
* @access public
*/
publicfunctionprepare($sql){
return@mysqli_prepare($this->_link,$sql);
}
/**
* mysqli_stmt_execute
* @param stmt object
* @param message string
* @return bool
* @access public
*/
publicfunctionstmt_execute($stmt,$message){
@mysqli_stmt_execute($stmt)ordie($message. mysqli_error($this->_link));
}
}
使用:
代碼如下復制代碼define("__HOST__","localhost");
define("__USER__","root");
define("__PASSWORD__","");
define("__DATABASE__","eee");
$db= DB::getInstance();