PHP單例模式應(yīng)用示例【多次連接數(shù)據(jù)庫(kù)只實(shí)例化一次】
本文實(shí)例講述了PHP單例模式應(yīng)用。分享給大家供大家參考,具體如下:
以前剛開(kāi)始工作的時(shí)候經(jīng)常連接數(shù)據(jù)庫(kù),每次用到數(shù)據(jù)庫(kù)的時(shí)候就要用new進(jìn)行實(shí)例并連接一次,當(dāng)時(shí)因?yàn)檫B接數(shù)據(jù)庫(kù)的次數(shù)不是很頻繁,所以也沒(méi)什么。后來(lái)主管對(duì)我說(shuō)我現(xiàn)在這樣每次都連接數(shù)據(jù)庫(kù)的如果數(shù)據(jù)讀取頻繁的話對(duì)數(shù)據(jù)庫(kù)和系統(tǒng)造成的壓力會(huì)很大,讓我想想辦法能不能就連接一次數(shù)據(jù)庫(kù)然后再次用到的時(shí)候就不用new一個(gè)新的連接了,當(dāng)時(shí)怎么也沒(méi)想到好的辦法,知道最近學(xué)到了單例模式才恍然大悟,當(dāng)時(shí)主管是引導(dǎo)我用單例模式的,只怪我以前對(duì)開(kāi)發(fā)模式不懂。好了廢話少說(shuō),下面來(lái)看單例模式:
單例模式(職責(zé)模式):
簡(jiǎn)單的說(shuō),一個(gè)對(duì)象(在學(xué)習(xí)設(shè)計(jì)模式之前,需要比較了解面向?qū)ο笏枷耄┲回?fù)責(zé)一個(gè)特定的任務(wù);
單例類:
1、構(gòu)造函數(shù)需要標(biāo)記為private
(訪問(wèn)控制:防止外部代碼使用new操作符創(chuàng)建對(duì)象),單例類不能在其他類中實(shí)例化,只能被其自身實(shí)例化;
2、擁有一個(gè)保存類的實(shí)例的靜態(tài)成員變量
3、擁有一個(gè)訪問(wèn)這個(gè)實(shí)例的公共的靜態(tài)方法(常用getInstance()
方法進(jìn)行實(shí)例化單例類,通過(guò)instanceof
操作符可以檢測(cè)到類是否已經(jīng)被實(shí)例化)
另外,需要?jiǎng)?chuàng)建__clone()
方法防止對(duì)象被復(fù)制(克?。?/p>
為什么要使用PHP單例模式?
1、php的應(yīng)用主要在于數(shù)據(jù)庫(kù)應(yīng)用, 所以一個(gè)應(yīng)用中會(huì)存在大量的數(shù)據(jù)庫(kù)操作, 使用單例模式, 則可以避免大量的new
操作消耗的資源。
2、如果系統(tǒng)中需要有一個(gè)類來(lái)全局控制某些配置信息, 那么使用單例模式可以很方便的實(shí)現(xiàn). 這個(gè)可以參看ZF的FrontController部分。
3、在一次頁(yè)面請(qǐng)求中, 便于進(jìn)行調(diào)試, 因?yàn)樗械拇a(例如數(shù)據(jù)庫(kù)操作類db)都集中在一個(gè)類中, 我們可以在類中設(shè)置鉤子, 輸出日志,從而避免到處var_dump
, echo
。
代碼(官方文檔中的):
<?php class Singletons{ // 保存類實(shí)例在此屬性中 private static $instance; // 構(gòu)造方法聲明為private,防止直接創(chuàng)建對(duì)象 private function __construct() { echo 'Iam constructed'; } // singleton 方法 public static function singleton() { if (!isset(self::$instance)) { $c = __CLASS__; self::$instance =new$c; } return self::$instance; } // Example類中的普通方法 public function bark() { echo 'Woof!'; } // 阻止用戶復(fù)制對(duì)象實(shí)例 public function __clone() { trigger_error('Clone is not allowed.',E_USER_ERROR); } }//endclass singletons //這個(gè)寫(xiě)法會(huì)出錯(cuò),因?yàn)闃?gòu)造方法被聲明為private //$test= new Singletons(); // 下面將得到Example類的單例對(duì)象 $test= Singletons::singleton(); $test->bark(); // 復(fù)制對(duì)象將導(dǎo)致一個(gè)E_USER_ERROR. $test_clone= clone $test; ?>
結(jié)果:
I am constructed! Woof!
Fatal error:
Clone is not allowed. in E:\APMServ5.2.6\www\htdocs\Lee\myprogram\other\class\singletons.phpon line 31
以下內(nèi)容源自網(wǎng)絡(luò)(可以參考學(xué)習(xí)一下):
單例模式的三個(gè)要點(diǎn):
(1). 需要一個(gè)保存類的唯一實(shí)例的靜態(tài)成員變量:
private static $_instance;
(2). 構(gòu)造函數(shù)和克隆函數(shù)必須聲明為私有的,防止外部程序new類從而失去單例模式的意義:
private function __construct() { $this->_db = pg_connect('xxxx'); } private function __clone() { }//覆蓋__clone()方法,禁止克隆
(3). 必須提供一個(gè)訪問(wèn)這個(gè)實(shí)例的公共的靜態(tài)方法(通常為getInstance
方法),從而返回唯一實(shí)例的一個(gè)引用
public static function getInstance() { if(! (self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; }
二、為什么要使用單例模式?
1、PHP缺點(diǎn):
PHP語(yǔ)言是一種解釋型的腳本語(yǔ)言,這種運(yùn)行機(jī)制使得每個(gè)PHP頁(yè)面被解釋執(zhí)行后,所有的相關(guān)資源都會(huì)被回收。也就是說(shuō),PHP在語(yǔ)言級(jí)別上沒(méi)有辦法讓某個(gè)對(duì)象常駐內(nèi)存,這和asp.NET、Java等編譯型是不同的,比如在Java中單例會(huì)一直存在于整個(gè)應(yīng)用程序的生命周期里,變量是跨頁(yè)面級(jí)的,真正可以做到這個(gè)實(shí)例在應(yīng)用程序生命周期中的唯一性。然而在PHP中,所有的變量無(wú)論是全局變量還是類的靜態(tài)成員,都是頁(yè)面級(jí)的,每次頁(yè)面被執(zhí)行時(shí),都會(huì)重新建立新的對(duì)象,都會(huì)在頁(yè)面執(zhí)行完畢后被清空,這樣似乎PHP單例模式就沒(méi)有什么意義了,所以PHP單例模式我覺(jué)得只是針對(duì)單次頁(yè)面級(jí)請(qǐng)求時(shí)出現(xiàn)多個(gè)應(yīng)用場(chǎng)景并需要共享同一對(duì)象資源時(shí)是非常有意義的。
2、單例模式在PHP中的應(yīng)用場(chǎng)合:
(1)、應(yīng)用程序與數(shù)據(jù)庫(kù)交互
一個(gè)應(yīng)用中會(huì)存在大量的數(shù)據(jù)庫(kù)操作,比如過(guò)數(shù)據(jù)庫(kù)句柄來(lái)連接數(shù)據(jù)庫(kù)這一行為,使用單例模式可以避免大量的new操作,因?yàn)槊恳淮?code>new操作都會(huì)消耗內(nèi)存資源和系統(tǒng)資源。
(2)、控制配置信息
如果系統(tǒng)中需要有一個(gè)類來(lái)全局控制某些配置信息,那么使用單例模式可以很方便的實(shí)現(xiàn).
三、如何實(shí)現(xiàn)單例模式?
1、普通的數(shù)據(jù)庫(kù)訪問(wèn)例子:
<?php ...... //初始化一個(gè)數(shù)據(jù)庫(kù)句柄 $db = new DB(...); //添加用戶信息 $db->addUserInfo(...); ...... //在函數(shù)中訪問(wèn)數(shù)據(jù)庫(kù),查找用戶信息 function getUserInfo() { $db = new DB(...);//再次new 數(shù)據(jù)庫(kù)類,和數(shù)據(jù)庫(kù)建立連接 $db = query(....);//根據(jù)查詢語(yǔ)句訪問(wèn)數(shù)據(jù)庫(kù) } ?>
2、應(yīng)用單例模式對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作:
<?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(...); ?>
3、深入理解
<?php class db { public $conn; public static $sql; public static $instance=null; private function __construct(){ require_once('db.config.php'); $this->conn = mysql_connect($db['host'],$db['user'],$db['password']); if(!mysql_select_db($db['database'],$this->conn)){ echo "失敗"; }; mysql_query('set names utf8',$this->conn); } public static function getInstance(){ if(is_null(self::$instance)){ self::$instance = new db; } return self::$instance; } /** * 查詢數(shù)據(jù)庫(kù) */ public function select($table,$condition=array(),$field = array()){ $where=''; if(!empty($condition)){ foreach($condition as $k=>$v){ $where.=$k."='".$v."' and "; } $where='where '.$where .'1=1'; } $fieldstr = ''; if(!empty($field)){ foreach($field as $k=>$v){ $fieldstr.= $v.','; } $fieldstr = rtrim($fieldstr,','); }else{ $fieldstr = '*'; } self::$sql = "select {$fieldstr} from {$table} {$where}"; $result=mysql_query(self::$sql,$this->conn); $resuleRow = array(); $i = 0; while($row=mysql_fetch_assoc($result)){ foreach($row as $k=>$v){ $resuleRow[$i][$k] = $v; } $i++; } return $resuleRow; } /** * 添加一條記錄 */ public function insert($table,$data){ $values = ''; $datas = ''; foreach($data as $k=>$v){ $values.=$k.','; $datas.="'$v'".','; } $values = rtrim($values,','); $datas = rtrim($datas,','); self::$sql = "INSERT INTO {$table} ({$values}) VALUES ({$datas})"; if(mysql_query(self::$sql)){ return mysql_insert_id(); }else{ return false; }; } /** * 修改一條記錄 */ public function update($table,$data,$condition=array()){ $where=''; if(!empty($condition)){ foreach($condition as $k=>$v){ $where.=$k."='".$v."' and "; } $where='where '.$where .'1=1'; } $updatastr = ''; if(!empty($data)){ foreach($data as $k=>$v){ $updatastr.= $k."='".$v."',"; } $updatastr = 'set '.rtrim($updatastr,','); } self::$sql = "update {$table} {$updatastr} {$where}"; return mysql_query(self::$sql); } /** * 刪除記錄 */ public function delete($table,$condition){ $where=''; if(!empty($condition)){ foreach($condition as $k=>$v){ $where.=$k."='".$v."' and "; } $where='where '.$where .'1=1'; } self::$sql = "delete from {$table} {$where}"; return mysql_query(self::$sql); } public static function getLastSql(){ echo self::$sql; } } $db = db::getInstance(); //$list = $db->select('demo',array('name'=>'tom','password'=>'ds'),array('name','password')); //echo $db->insert('demo',array('name'=>'最近你啦','password'=>'123')); //echo $db->update('demo',array("name"=>'xxx',"password"=>'123'),array('id'=>1)); echo $db->delete('demo',array('id'=>'2')); db::getLastSql(); echo "<pre>"; ?>
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》、《PHP數(shù)組(Array)操作技巧大全》、《PHP基本語(yǔ)法入門(mén)教程》、《PHP運(yùn)算與運(yùn)算符用法總結(jié)》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門(mén)教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
- PHP單例模式數(shù)據(jù)庫(kù)連接類與頁(yè)面靜態(tài)化實(shí)現(xiàn)方法
- PHP中數(shù)據(jù)庫(kù)單例模式的實(shí)現(xiàn)代碼分享
- PHP基于單例模式實(shí)現(xiàn)的數(shù)據(jù)庫(kù)操作基類
- PHP實(shí)現(xiàn)單例模式最安全的做法
- php單例模式的簡(jiǎn)單實(shí)現(xiàn)方法
- php利用單例模式實(shí)現(xiàn)日志處理類庫(kù)
- PHP基于單例模式編寫(xiě)PDO類的方法
- PHP最常用的2種設(shè)計(jì)模式工廠模式和單例模式介紹
- PHP設(shè)計(jì)模式之工廠模式與單例模式
- PHP實(shí)現(xiàn)單例模式建立數(shù)據(jù)庫(kù)連接的方法分析
相關(guān)文章
php使用CutyCapt實(shí)現(xiàn)網(wǎng)頁(yè)截圖保存的方法
這篇文章主要介紹了php使用CutyCapt實(shí)現(xiàn)網(wǎng)頁(yè)截圖保存的方法,結(jié)合實(shí)例形式詳細(xì)分析了CutyCapt的下載、安裝及php使用CutyCapt進(jìn)行截圖與保存的相關(guān)操作技巧,需要的朋友可以參考下2016-10-10php實(shí)現(xiàn)將HTML頁(yè)面轉(zhuǎn)換成word并且保存的方法
這篇文章主要介紹了php實(shí)現(xiàn)將HTML頁(yè)面轉(zhuǎn)換成word并且保存的方法,結(jié)合實(shí)例形式分析了PHPWord工具的功能與使用方法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10使用PHP接收POST數(shù)據(jù),解析json數(shù)據(jù)
本篇文章是對(duì)使用PHP接收POST數(shù)據(jù)以及json數(shù)據(jù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06PHP實(shí)現(xiàn)JS中escape與unescape的方法
這篇文章主要介紹了PHP實(shí)現(xiàn)JS中escape與unescape的方法,通過(guò)json_encode和json_decode方法實(shí)現(xiàn)JS中escape與unescape函數(shù)的功能,需要的朋友可以參考下2016-07-07docker?中搭建php環(huán)境經(jīng)驗(yàn)分享
這篇文章主要介紹了docker?中搭建php環(huán)境經(jīng)驗(yàn)分享的相關(guān)資料,需要的朋友可以參考下2023-09-09php批量刪除cookie的簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了php批量刪除cookie的簡(jiǎn)單實(shí)現(xiàn)方法,實(shí)例分析了刪除單個(gè)cookie及數(shù)組遍歷的方式批量刪除cookie的技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2015-01-01深入講解PHP的對(duì)象注入(Object Injection)
這篇文章主要介紹了PHP中對(duì)象注入的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-03-03