PHP 单例模式解析和实战

一、什么是单例模式?

1、含义

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

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

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

[php]view plaincopyprint?

  1. private static $_instance;

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

[php]view plaincopyprint?

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

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

[php]view plaincopyprint?

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

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

1、PHP缺点:

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

数据库交互

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

(2)、控制配置信息

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

三、如何实现单例模式?

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

[php]view plaincopyprint?

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

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

[php]view plaincopyprint?

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

3、深入理解

[php]view plaincopyprint?

    1. <?php
    2. class db {
    3. public $conn;
    4. public static $sql;
    5. public static $instance=null;
    6. private function __construct(){
    7. require_once('db.config.php');
    8. $this->conn = mysql_connect($db['host'],$db['user'],$db['password']);
    9. if(!mysql_select_db($db['database'],$this->conn)){
    10. echo "失败";
    11. };
    12. mysql_query('set names utf8',$this->conn);
    13. }
    14. public static function getInstance(){
    15. if(is_null(self::$instance)){
    16. self::$instance = new db;
    17. }
    18. return self::$instance;
    19. }
    20. /**
    21. * 查询数据库
    22. */
    23. public function select($table,$condition=array(),$field = array()){
    24. $where='';
    25. if(!empty($condition)){
    26. foreach($condition as $k=>$v){
    27. $where.=$k."='".$v."' and ";
    28. }
    29. $where='where '.$where .'1=1';
    30. }
    31. $fieldstr = '';
    32. if(!empty($field)){
    33. foreach($field as $k=>$v){
    34. $fieldstr.= $v.',';
    35. }
    36. $fieldstr = rtrim($fieldstr,',');
    37. }else{
    38. $fieldstr = '*';
    39. }
    40. self::$sql = "select {$fieldstr} from {$table} {$where}";
    41. $result=mysql_query(self::$sql,$this->conn);
    42. $resuleRow = array();
    43. $i = 0;
    44. while($row=mysql_fetch_assoc($result)){
    45. foreach($row as $k=>$v){
    46. $resuleRow[$i][$k] = $v;
    47. }
    48. $i++;
    49. }
    50. return $resuleRow;
    51. }
    52. /**
    53. * 添加一条记录
    54. */
    55. public function insert($table,$data){
    56. $values = '';
    57. $datas = '';
    58. foreach($data as $k=>$v){
    59. $values.=$k.',';
    60. $datas.="'$v'".',';
    61. }
    62. $values = rtrim($values,',');
    63. $datas = rtrim($datas,',');
    64. self::$sql = "INSERT INTO {$table} ({$values}) VALUES ({$datas})";
    65. if(mysql_query(self::$sql)){
    66. return mysql_insert_id();
    67. }else{
    68. return false;
    69. };
    70. }
    71. /**
    72. * 修改一条记录
    73. */
    74. public function update($table,$data,$condition=array()){
    75. $where='';
    76. if(!empty($condition)){
    77. foreach($condition as $k=>$v){
    78. $where.=$k."='".$v."' and ";
    79. }
    80. $where='where '.$where .'1=1';
    81. }
    82. $updatastr = '';
    83. if(!empty($data)){
    84. foreach($data as $k=>$v){
    85. $updatastr.= $k."='".$v."',";
    86. }
    87. $updatastr = 'set '.rtrim($updatastr,',');
    88. }
    89. self::$sql = "update {$table} {$updatastr} {$where}";
    90. return mysql_query(self::$sql);
    91. }
    92. /**
    93. * 删除记录
    94. */
    95. public function delete($table,$condition){
    96. $where='';
    97. if(!empty($condition)){
    98. foreach($condition as $k=>$v){
    99. $where.=$k."='".$v."' and ";
    100. }
    101. $where='where '.$where .'1=1';
    102. }
    103. self::$sql = "delete from {$table} {$where}";
    104. return mysql_query(self::$sql);
    105. }
    106. public static function getLastSql(){
    107. echo self::$sql;
    108. }
    109. }
    110. $db = db::getInstance();
    111. //$list = $db->select('demo',array('name'=>'tom','password'=>'ds'),array('name','password'));
    112. //echo $db->insert('demo',array('name'=>'最近你啦','password'=>'123'));
    113. //echo $db->update('demo',array("name"=>'xxx',"password"=>'123'),array('id'=>1));
    114. echo $db->delete('demo',array('id'=>'2'));
    115. db::getLastSql();
    116. echo "<pre>";
    117. ?>