当前位置:首页 > PHP教程 > php应用 > 列表

PHP单例模式是什么 php实现单例模式的方法

发布:smiling 来源: PHP粉丝网  添加日期:2021-08-05 10:26:01 浏览: 评论:0 

PHP单例模式是什么?这篇文章主要介绍了php实现单例模式的方法,告诉大家为什么使用单例模式,感兴趣的朋友可以参考一下。

一、什么是单例模式?

1、含义

作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。

2、单例模式的三个要点:

(1). 需要一个保存类的唯一实例的静态成员变量:

private static $_instance;   

(2). 构造函数和克隆函数必须声明为私有的,防止外部程序new类从而失去单例模式的意义:

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

(3). 必须提供一个访问这个实例的公共的静态方法(通常为getInstance方法),从而返回唯一实例的一个引用

  1. public static function getInstance()   
  2. {   
  3.   if(! (self::$_instance instanceof self) )   
  4.   {   
  5.     self::$_instance = new self();   
  6.   }  
  7.   return self::$_instance;   
  8.    
  9. } 

二、为什么要使用单例模式?

1、PHP缺点:

PHP语言是一种解释型的脚本语言,这种运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收。也就是说,PHP在语言级别上没有办法让某个对象常驻内存,这和asp.net、Java等编译型是不同的,比如在Java中单例会一直存在于整个应用程序的生命周期里,变量是跨页面级的,真正可以做到这个实例在应用程序生命周期中的唯一性。然而在PHP中,所有的变量无论是全局变量还是类的静态成员,都是页面级的,每次页面被执行时,都会重新建立新的对象,都会在页面执行完毕后被清空,这样似乎PHP单例模式就没有什么意义了,所以PHP单例模式我觉得只是针对单次页面级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的。

2、单例模式在PHP中的应用场合:

(1)、应用程序与数据库交互

一个应用中会存在大量的数据库操作,比如过数据库句柄来连接数据库这一行为,使用单例模式可以避免大量的new操作,因为每一次new操作都会消耗内存资源和系统资源。

(2)、控制配置信息

如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现.

三、如何实现单例模式?

1、普通的数据库访问例子:

  1. <?php  
  2. ......  
  3. //初始化一个数据库句柄  
  4. $db = new DB(...);  
  5.    
  6. //添加用户信息  
  7. $db->addUserInfo(...);  
  8.    
  9. ......  
  10.    
  11. //在函数中访问数据库,查找用户信息  
  12. function getUserInfo()  
  13. {  
  14.   $db = new DB(...);//再次new 数据库类,和数据库建立连接  
  15.   $db = query(....);//根据查询语句访问数据库  
  16. }  
  17.    
  18. ?> 

2、应用单例模式对数据库进行操作:

  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.   {   
  27.   }  
  28.    
  29. }  
  30.    
  31. //test   
  32. $db = DB::getInstance();   
  33. $db->addUserInfo(...);   
  34. $db->getUserInfo(...);   
  35.    
  36. ?>  

下面的代码是PDO操作数据库类的一个封装,采用了单例模式:

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

调用方法:

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

以上就是本文的全部内容,希望对大家学习php程序设计有所帮助。

Tags: PHP单例模式

分享到: