国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > PHP > 正文

PHP 單例模式優(yōu)點意義及如何實現(xiàn)

2024-05-04 21:50:36
字體:
供稿:網(wǎng)友

一、什么是單例模式?

1、含義   

作為對象的創(chuàng)建模式,單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統(tǒng)全局地提供這個實例。它不會創(chuàng)建實例副本,而是會向單例類內(nèi)部存儲的實例返回一個引用。

2、單例模式的三個要點:

(1). 需要一個保存類的唯一實例的靜態(tài)成員變量:

private static $_instance; 

(2). 構(gòu)造函數(shù)和克隆函數(shù)必須聲明為私有的,防止外部程序new類從而失去單例模式的意義:

  1. private function __construct(){    
  2.     $this->_db = pg_connect('xxxx');   
  3. }    
  4. private function __clone()   
  5. {   
  6. }//覆蓋__clone()方法,禁止克隆  

(3). 必須提供一個訪問這個實例的公共的靜態(tài)方法(通常為getInstance方法),從而返回唯一實例的一個引用.

  1. public static function getInstance(){     
  2.     if(! (self::$_instance instanceof self) )    
  3.     {     
  4.         self::$_instance = new self();     
  5.     }   
  6.     return self::$_instance
  7. }    
二、為什么要使用單例模式?

多數(shù)人都是從單例模式的字面上的意思來理解它的用途, 認為這是對系統(tǒng)資源的節(jié)省, 可以避免重復(fù)實例化, 是一種"計劃生育".   而PHP每次執(zhí)行完頁面都是會從內(nèi)存中清理掉所有的資源. 因而PHP中的單例實際每次運行都是需要重新實例化的, 這樣就失去了單例重復(fù)實例化的意義了. 單單從這個方面來說, PHP的單例的確有點讓各位失望. 但是單例僅僅只有這個功能和應(yīng)用嗎? 答案是否定的,我們一起來看看。

php的應(yīng)用主要在于數(shù)據(jù)庫應(yīng)用, 所以一個應(yīng)用中會存在大量的數(shù)據(jù)庫操作, 在使用面向?qū)ο蟮姆绞介_發(fā)時(廢話), 如果使用單例模式, 則可以避免大量的new 操作消耗的資源。

如果系統(tǒng)中需要有一個類來全局控制某些配置信息, 那么使用單例模式可以很方便的實現(xiàn). 這個可以參看zend Framework的FrontController部分。

在一次頁面請求中, 便于進行調(diào)試, 因為所有的代碼(例如數(shù)據(jù)庫操作類db)都集中在一個類中, 我們可以在類中設(shè)置鉤子, 輸出日志,從而避免到處var_dump, echo。

1、PHP缺點:

PHP語言是一種解釋型的腳本語言,這種運行機制使得每個PHP頁面被解釋執(zhí)行后,所有的相關(guān)資源都會被回收。也就是說,PHP在語言級別上沒有辦法讓某個對象常駐內(nèi)存,這和asp.net、Java等編譯型是不同的,比如在Java中單例會一直存在于整個應(yīng)用程序的生命周期里,變量是跨頁面級的,真正可以做到這個實例在應(yīng)用程序生命周期中的唯一性。然而在PHP中,所有的變量無論是全局變量還是類的靜態(tài)成員,都是頁面級的,每次頁面被執(zhí)行時,都會重新建立新的對象,都會在頁面執(zhí)行完畢后被清空,這樣似乎PHP單例模式就沒有什么意義了,所以PHP單例模式我覺得只是針對單次頁面級請求時出現(xiàn)多個應(yīng)用場景并需要共享同一對象資源時是非常有意義的。

2、單例模式在PHP中的應(yīng)用場合:

(1)、應(yīng)用程序與數(shù)據(jù)庫交互

一個應(yīng)用中會存在大量的數(shù)據(jù)庫操作,比如過數(shù)據(jù)庫句柄來連接數(shù)據(jù)庫這一行為,使用單例模式可以避免大量的new操作,因為每一次new操作都會消耗內(nèi)存資源和系統(tǒng)資源。

(2)、控制配置信息

如果系統(tǒng)中需要有一個類來全局控制某些配置信息, 那么使用單例模式可以很方便的實現(xiàn).

三、如何實現(xiàn)單例模式?

1、普通的數(shù)據(jù)庫訪問例子:

  1. <?php   
  2. ......   
  3. //初始化一個數(shù)據(jù)庫句柄   
  4. $db = new DB(...);   
  5.     
  6. //添加用戶信息   
  7. $db->addUserInfo(...);   
  8.     
  9. ......   
  10.     
  11. //在函數(shù)中訪問數(shù)據(jù)庫,查找用戶信息   
  12. function getUserInfo()   
  13. {   
  14.     $db = new DB(...);//再次new 數(shù)據(jù)庫類,和數(shù)據(jù)庫建立連接   
  15.     $db = query(....);//根據(jù)查詢語句訪問數(shù)據(jù)庫   
  16. }   
  17.     
  18. ?> 

2、應(yīng)用單例模式對數(shù)據(jù)庫進行操作:

  1. <?php  
  2. class DB     
  3. {     
  4.     private $_db;     
  5.     private static $_instance;     
  6.       
  7.     private function __construct(...)     
  8.     {     
  9.         $this->_db = pg_connect(...);//postgrsql     
  10.     }     
  11.       
  12.     private function __clone() {};  //覆蓋__clone()方法,禁止克隆     
  13.       
  14.     public static function getInstance()     
  15.     {     
  16.         if(! (self::$_instance instanceof self) ) {     
  17.             self::$_instance = new self();     
  18.         }     
  19.         return self::$_instance;     
  20.     }     
  21.       
  22.     public function addUserInfo(...)   
  23.     {   
  24.     }   
  25.      public function getUserInfo(...)   
  26.     {   //Vevb.com 
  27.     }   
  28.     
  29. }   
  30.     
  31. //test     
  32. $db = DB::getInstance();     
  33. $db->addUserInfo(...);     
  34. $db->getUserInfo(...);    
  35.     
  36. ?> 

下面的代碼是PDO操作數(shù)據(jù)庫類的一個封裝,采用了單例模式:

  1. <?php 
  2. /** 
  3.  * MyPDO 
  4.  */ 
  5. class MyPDO 
  6.     protected static $_instance = null; 
  7.     protected $dbName = ''
  8.     protected $dsn
  9.     protected $dbh
  10.       
  11.     /** 
  12.      * 構(gòu)造 
  13.      *  
  14.      * @return MyPDO 
  15.      */ 
  16.     private function __construct($dbHost$dbUser$dbPasswd$dbName$dbCharset
  17.     { 
  18.         try { 
  19.             $this->dsn = 'mysql:host='.$dbHost.';dbname='.$dbName
  20.             $this->dbh = new PDO($this->dsn, $dbUser$dbPasswd); 
  21.             $this->dbh->exec('SET character_set_connection='.$dbCharset.', character_set_results='.$dbCharset.', character_set_client=binary'); 
  22.         } <a href="/"/tags.php/catch//"" target="/"_blank/"">catch</a> (PDOException $e) { 
  23.             $this->outputError($e->getMessage()); 
  24.         } 
  25.     } 
  26.       
  27.     /** 
  28.      * 防止克隆 
  29.      *  
  30.      */ 
  31.     private function __clone() {} 
  32.       
  33.     /** 
  34.      * Singleton instance 
  35.      *  
  36.      * @return Object 
  37.      */ 
  38.     public static function getInstance($dbHost$dbUser$dbPasswd$dbName$dbCharset
  39.     { 
  40.         if (self::$_instance === null) { 
  41.             self::$_instance = new self($dbHost$dbUser$dbPasswd$dbName$dbCharset); 
  42.         } 
  43.         return self::$_instance
  44.     } 
  45.       
  46.     /** 
  47.      * Query 查詢 
  48.      * 
  49.      * @param String $strSql SQL語句 
  50.      * @param String $queryMode 查詢方式(All or Row) 
  51.      * @param Boolean $debug 
  52.      * @return Array 
  53.      */ 
  54.     public function query($strSql$queryMode = 'All'$debug = false) 
  55.     { 
  56.         if ($debug === true) $this->debug($strSql); 
  57.         $recordset = $this->dbh->query($strSql); 
  58.         $this->getPDOError(); 
  59.         if ($recordset) { 
  60.             $recordset->setFetchMode(PDO::FETCH_ASSOC); 
  61.             if ($queryMode == 'All') { 
  62.                 $result = $recordset->fetchAll(); 
  63.             } elseif ($queryMode == 'Row') { 
  64.                 $result = $recordset->fetch(); 
  65.             } 
  66.         } else { 
  67.             $result = null; 
  68.         } 
  69.         return $result
  70.     } 
  71.       
  72.     /** 
  73.      * Update 更新 
  74.      * 
  75.      * @param String $table 表名 
  76.      * @param Array $arrayDataValue 字段與值 
  77.      * @param String $where 條件 
  78.      * @param Boolean $debug 
  79.      * @return Int 
  80.      */ 
  81.     public function update($table$arrayDataValue$where = ''$debug = false) 
  82.     { 
  83.         $this->checkFields($table$arrayDataValue); 
  84.         if ($where) { 
  85.             $strSql = ''
  86.             <a href="/"/tags.php/foreach//"" target="/"_blank/"">foreach</a> ($arrayDataValue as $key => $value) { 
  87.                 $strSql .= ", `$key`='$value'"
  88.             } 
  89.             $strSql = <a href="/"/tags.php/substr//"" target="/"_blank/"">substr</a>($strSql, 1); 
  90.             $strSql = "UPDATE `$table` SET $strSql WHERE $where"
  91.         } else { 
  92.             $strSql = "REPLACE INTO `$table` (`".implode('`,`'array_keys($arrayDataValue))."`) VALUES ('".implode("','"$arrayDataValue)."')"
  93.         } 
  94.         if ($debug === true) $this->debug($strSql); 
  95.         $result = $this->dbh->exec($strSql); 
  96.         $this->getPDOError(); 
  97.         return $result
  98.     } 
  99.       
  100.     /** 
  101.      * Insert 插入 
  102.      * 
  103.      * @param String $table 表名 
  104.      * @param Array $arrayDataValue 字段與值 
  105.      * @param Boolean $debug 
  106.      * @return Int 
  107.      */ 
  108.     public function insert($table$arrayDataValue$debug = false) 
  109.     { 
  110.         $this->checkFields($table$arrayDataValue); 
  111.         $strSql = "INSERT INTO `$table` (`".implode('`,`'array_keys($arrayDataValue))."`) VALUES ('".implode("','"$arrayDataValue)."')"
  112.         if ($debug === true) $this->debug($strSql); 
  113.         $result = $this->dbh->exec($strSql); 
  114.         $this->getPDOError(); 
  115.         return $result
  116.     } 
  117.       
  118.     /** 
  119.      * Replace 覆蓋方式插入 
  120.      * 
  121.      * @param String $table 表名 
  122.      * @param Array $arrayDataValue 字段與值 
  123.      * @param Boolean $debug 
  124.      * @return Int 
  125.      */ 
  126.     public function replace($table$arrayDataValue$debug = false) 
  127.     { 
  128.         $this->checkFields($table$arrayDataValue); 
  129.         $strSql = "REPLACE INTO `$table`(`".implode('`,`'array_keys($arrayDataValue))."`) VALUES ('".implode("','"$arrayDataValue)."')"
  130.         if ($debug === true) $this->debug($strSql); 
  131.         $result = $this->dbh->exec($strSql); 
  132.         $this->getPDOError(); 
  133.         return $result
  134.     } 
  135.       
  136.     /** 
  137.      * Delete 刪除 
  138.      * 
  139.      * @param String $table 表名 
  140.      * @param String $where 條件 
  141.      * @param Boolean $debug 
  142.      * @return Int 
  143.      */ 
  144.     public function delete($table$where = ''$debug = false) 
  145.     { 
  146.         if ($where == '') { 
  147.             $this->outputError("'WHERE' is Null"); 
  148.         } else { 
  149.             $strSql = "DELETE FROM `$table` WHERE $where"
  150.             if ($debug === true) $this->debug($strSql); 
  151.             $result = $this->dbh->exec($strSql); 
  152.             $this->getPDOError(); 
  153.             return $result
  154.         } 
  155.     } 
  156.       
  157.     /** 
  158.      * execSql 執(zhí)行SQL語句 
  159.      * 
  160.      * @param String $strSql 
  161.      * @param Boolean $debug 
  162.      * @return Int 
  163.      */ 
  164.     public function execSql($strSql$debug = false) 
  165.     { 
  166.         if ($debug === true) $this->debug($strSql); 
  167.         $result = $this->dbh->exec($strSql); 
  168.         $this->getPDOError(); 
  169.         return $result
  170.     } 
  171.       
  172.     /** 
  173.      * 獲取字段最大值 
  174.      *  
  175.      * @param string $table 表名 
  176.      * @param string $field_name 字段名 
  177.      * @param string $where 條件 
  178.      */ 
  179.     public function getMaxValue($table$field_name$where = ''$debug = false) 
  180.     { 
  181.         $strSql = "SELECT MAX(".$field_name.") AS MAX_VALUE FROM $table"
  182.         if ($where != ''$strSql .= " WHERE $where"
  183.         if ($debug === true) $this->debug($strSql); 
  184.         $arrTemp = $this->query($strSql'Row'); 
  185.         $maxValue = $arrTemp["MAX_VALUE"]; 
  186.         if ($maxValue == "" || $maxValue == null) { 
  187.             $maxValue = 0; 
  188.         } 
  189.         return $maxValue
  190.     } 
  191.       
  192.     /** 
  193.      * 獲取指定列的數(shù)量 
  194.      *  
  195.      * @param string $table 
  196.      * @param string $field_name 
  197.      * @param string $where 
  198.      * @param bool $debug 
  199.      * @return int 
  200.      */ 
  201.     public function getCount($table$field_name$where = ''$debug = false) 
  202.     { 
  203.         $strSql = "SELECT COUNT($field_name) AS NUM FROM $table"
  204.         if ($where != ''$strSql .= " WHERE $where"
  205.         if ($debug === true) $this->debug($strSql); 
  206.         $arrTemp = $this->query($strSql'Row'); 
  207.         return $arrTemp['NUM']; 
  208.     } 
  209.       
  210.     /** 
  211.      * 獲取表引擎 
  212.      *  
  213.      * @param String $dbName 庫名 
  214.      * @param String $tableName 表名 
  215.      * @param Boolean $debug 
  216.      * @return String 
  217.      */ 
  218.     public function getTableEngine($dbName$tableName
  219.     { 
  220.         $strSql = "SHOW TABLE STATUS FROM $dbName WHERE Name='".$tableName."'"
  221.         $arrayTableInfo = $this->query($strSql); 
  222.         $this->getPDOError(); 
  223.         return $arrayTableInfo[0]['Engine']; 
  224.     } 
  225.       
  226.     /** 
  227.      * beginTransaction 事務(wù)開始 
  228.      */ 
  229.     private function beginTransaction() 
  230.     { 
  231.         $this->dbh->beginTransaction(); 
  232.     } 
  233.       
  234.     /** 
  235.      * commit 事務(wù)提交 
  236.      */ 
  237.     private function commit() 
  238.     { 
  239.         $this->dbh->commit(); 
  240.     } 
  241.       
  242.     /** 
  243.      * rollback 事務(wù)回滾 
  244.      */ 
  245.     private function rollback() 
  246.     { 
  247.         $this->dbh->rollback(); 
  248.     } 
  249.       
  250.     /** 
  251.      * transaction 通過事務(wù)處理多條SQL語句 
  252.      * 調(diào)用前需通過getTableEngine判斷表引擎是否支持事務(wù) 
  253.      * 
  254.      * @param array $arraySql 
  255.      * @return Boolean 
  256.      */ 
  257.     public function execTransaction($arraySql
  258.     { 
  259.         $retval = 1; 
  260.         $this->beginTransaction(); 
  261.         foreach ($arraySql as $strSql) { 
  262.             if ($this->execSql($strSql) == 0) $retval = 0; 
  263.         } 
  264.         if ($retval == 0) { 
  265.             $this->rollback(); 
  266.             return false; 
  267.         } else { 
  268.             $this->commit(); 
  269.             return true; 
  270.         } 
  271.     } 
  272.     /** 
  273.      * checkFields 檢查指定字段是否在指定數(shù)據(jù)表中存在 
  274.      * 
  275.      * @param String $table 
  276.      * @param array $arrayField 
  277.      */ 
  278.     private function checkFields($table$arrayFields
  279.     { 
  280.         $fields = $this->getFields($table); 
  281.         foreach ($arrayFields as $key => $value) { 
  282.             if (!in_array($key$fields)) { 
  283.                 $this->outputError("Unknown column `$key` in field list."); 
  284.             } 
  285.         } 
  286.     } 
  287.       
  288.     /** 
  289.      * getFields 獲取指定數(shù)據(jù)表中的全部字段名 
  290.      * 
  291.      * @param String $table 表名 
  292.      * @return array 
  293.      */ 
  294.     private function getFields($table
  295.     { 
  296.         $fields = array(); 
  297.         $recordset = $this->dbh->query("SHOW COLUMNS FROM $table"); 
  298.         $this->getPDOError(); 
  299.         $recordset->setFetchMode(PDO::FETCH_ASSOC); 
  300.         $result = $recordset->fetchAll(); 
  301.         foreach ($result as $rows) { 
  302.             $fields[] = $rows['Field']; 
  303.         } 
  304.         return $fields
  305.     } 
  306.       
  307.     /** 
  308.      * getPDOError 捕獲PDO錯誤信息 
  309.      */ 
  310.     private function getPDOError() 
  311.     { 
  312.         if ($this->dbh->errorCode() != '00000') { 
  313.             $arrayError = $this->dbh->errorInfo(); 
  314.             $this->outputError($arrayError[2]); 
  315.         } 
  316.     } 
  317.       
  318.     /** 
  319.      * debug 
  320.      *  
  321.      * @param mixed $debuginfo 
  322.      */ 
  323.     private function debug($debuginfo
  324.     { 
  325.         var_dump($debuginfo); 
  326.         exit(); 
  327.     } 
  328.       
  329.     /** 
  330.      * 輸出錯誤信息 
  331.      *  
  332.      * @param String $strErrMsg 
  333.      */ 
  334.     private function outputError($strErrMsg
  335.     { 
  336.         throw new Exception('MySQL Error: '.$strErrMsg); 
  337.     } 
  338.       
  339.     /** 
  340.      * destruct 關(guān)閉數(shù)據(jù)庫連接 
  341.      */ 
  342.     public function destruct() 
  343.     { 
  344.         $this->dbh = null; 
  345.     } 
  346. ?> 

調(diào)用方法:

  1. <?php 
  2. require 'MyPDO.class.php'
  3. $db = MyPDO::getInstance('localhost''root''123456''test''utf8'); 
  4. $db->query("<a href="/"/tags.php/select//"" target="/"_blank/"">select</a> count(*) frome table"); 
  5. $db->destruct(); 
  6. ?> 

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 大洼县| 大洼县| 多伦县| 雷山县| 大足县| 囊谦县| 兴安盟| 信宜市| 东山县| 西宁市| 成都市| 辽中县| 乌什县| 边坝县| 玛纳斯县| 兴城市| 伊金霍洛旗| 麻城市| 象州县| 梅州市| 普兰店市| 南部县| 米泉市| 上蔡县| 松溪县| 长宁县| 湘阴县| 滨州市| 保山市| 文安县| 会同县| 加查县| 周宁县| 治多县| 安宁市| 越西县| 嫩江县| 洛扎县| 正定县| 桦南县| 沁源县|