添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

以前刚开始工作的时候经常连接数据库,每次用到数据库的时候就要用new 进行实例并连接一次,当时因为连接数据库的次数不是很频繁,所以也没什么。后来主管对我说我现在这样每次都连接数据库的如果数据读取频繁的话对数据库和系统造成的压力会很大,让我想想办法能不能就连接一次数据库然后再次用到的时候就不用new一个新的连接了,当时怎么也没想到好的办法,知道最近学到了单例模式才恍然大悟,当时主管是引导我用单例模式的,只怪我以前对开发模式不懂。好了废话少说,下面来看单例模式:

单例模式(职责模式):

简单的说,一个对象(在学习设计模式之前,需要比较了解面向对象思想)只负责一个特定的任务;

1、构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化;

2、拥有一个保存类的实例的静态成员变量

3、拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)

另外,需要创建__clone()方法防止对象被复制(克隆)

为什么要使用PHP单例模式?

1、php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 使用单例模式, 则可以避免大量的new 操作消耗的资源。

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

3、在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。

代码(官方文档中的):

class Singletons{

// 保存类实例在此属性中

private static $instance ;

// 构造方法声明为 private ,防止直接创建对象

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!' ;

// 阻止用户复制对象实例

public function __clone()

trigger_error( 'Clone is not allowed.' ,E_USER_ERROR);

} //endclass singletons

// 这个写法会出错,因为构造方法被声明为 private

//$test= new Singletons();

// 下面将得到 Example 类的单例对象

$test= Singletons:: singleton ();

$test->bark();

// 复制对象将导致一个 E_USER_ERROR.

$test_clone= clone $test;

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

以下内容源自网络(可以参考学习一下):

单例模式的三个要点:

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

[php] view plain copy print ?

1. private static $_instance ;

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

[php] view plain copy print ?

1. private function __construct()

2. {

3. $this ->_db = pg_connect( 'xxxx' );

4. }

5. private function __clone()

6. {

7. } // 覆盖 __clone() 方法,禁止克隆

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

[php] view plain copy print ?

1. public static function getInstance()

2. {

3. if (! (self:: $_instance instanceof self) )

4. {

5. self:: $_instance = new self();

6. }

7. return self:: $_instance ;

9. }




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

1 、PHP 缺点:

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

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

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

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

(2)、控制配置信息

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

三、如何实现单例模式?

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

[php] view plain copy print ?

1. <?php

2. ......

3. // 初始化一个数据库句柄

4. $db = new DB(...);

6. // 添加用户信息

7. $db ->addUserInfo(...);

9. ......

11. // 在函数中访问数据库,查找用户信息

12. function getUserInfo()

13. {

14. $db = new DB(...); // 再次 new 数据库类,和数据库建立连接

15. $db = query(....); // 根据查询语句访问数据库

16. }

18. ?>

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

[php] view plain copy print ?

1. <?php

3. class DB

4. {

5. private $_db ;

6. private static $_instance ;

8. private function __construct(...)

9. {

10. $this ->_db = pg_connect(...); //postgrsql

11. }

13. private function __clone() {}; // 覆盖 __clone() 方法,禁止克隆

15. public static function getInstance()

16. {

17. if (! (self:: $_instance instanceof self) ) {

18. self:: $_instance = new self();

19. }

20. return self:: $_instance ;

21. }

25. public function addUserInfo(...)

26. {

30. }

32. public function getUserInfo(...)

33. {

35. }

37. }

39. //test

41. $db = DB::getInstance();

43. $db ->addUserInfo(...);

45. $db ->getUserInfo(...);

48. ?>


3 、深入理解

[php] view plain copy print ?

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 )){

27. foreach ( $condition as $k => $v ){

28. $where .= $k . "='" . $v . "' and " ;

29. }

30. $where = 'where ' . $where . '1=1' ;

31. }

32. $fieldstr = '' ;

33. if (!empty( $field )){

35. foreach ( $field as $k => $v ){

36. $fieldstr .= $v . ',' ;

37. }

38. $fieldstr = rtrim( $fieldstr , ',' );

39. } else {

40. $fieldstr = '*' ;

41. }

42. self:: $sql = "select {$fieldstr} from {$table} {$where}" ;

43. $result =mysql_query(self:: $sql , $this ->conn);

44. $resuleRow = array ();

45. $i = 0;

46. while ( $row =mysql_fetch_assoc( $result )){

47. foreach ( $row as $k => $v ){

48. $resuleRow [ $i ][ $k ] = $v ;

49. }

50. $i ++;

51. }

52. return $resuleRow ;

53. }

54. /**

55. * 添加一条记录

56. */

57. public function insert( $table , $data ){

58. $values = '' ;

59. $datas = '' ;

60. foreach ( $data as $k => $v ){

61. $values .= $k . ',' ;

62. $datas .= "'$v'" . ',' ;

63. }

64. $values = rtrim( $values , ',' );

65. $datas = rtrim( $datas , ',' );

66. self:: $sql = "INSERT INTO  {$table} ({$values}) VALUES ({$datas})" ;

67. if (mysql_query(self:: $sql )){

68. return mysql_insert_id();

69. } else {

70. return false;

71. };

72. }

73. /**

74. * 修改一条记录

75. */

76. public function update( $table , $data , $condition = array ()){

77. $where = '' ;

78. if (!empty( $condition )){

80. foreach ( $condition as $k => $v ){

81. $where .= $k . "='" . $v . "' and " ;

82. }

83. $where = 'where ' . $where . '1=1' ;

84. }

85. $updatastr = '' ;

86. if (!empty( $data )){

87. foreach ( $data as $k => $v ){

88. $updatastr .= $k . "='" . $v . "'," ;

89. }

90. $updatastr = 'set ' .rtrim( $updatastr , ',' );

91. }

92. self:: $sql = "update {$table} {$updatastr} {$where}" ;

93. return mysql_query(self:: $sql );

94. }

95. /**

96. * 删除记录

97. */

98. public function delete( $table , $condition ){

99. $where = '' ;

100. if (!empty( $condition )){

102. foreach ( $condition as $k => $v ){

103. $where .= $k . "='" . $v . "' and " ;

104. }

105. $where = 'where ' . $where . '1=1' ;

106. }

107. self:: $sql = "delete from {$table} {$where}" ;

108. return mysql_query(self:: $sql );

110. }

112. public static function getLastSql(){

113. echo self:: $sql ;

114. }

118. }

120. $db = db::getInstance();

121. //$list = $db->select('demo',array('name'=>'tom','password'=>'ds'),array('name','password'));

122. //echo $db->insert('demo',array('name'=>' 最近你啦 ','password'=>'123'));

123. //echo $db->update('demo',array("name"=>'xxx',"password"=>'123'),array('id'=>1));

124. echo $db ->delete( 'demo' , array ( 'id' => '2' ));

125. db::getLastSql();

126. echo "<pre>" ;

127. ?>

什么是 数据库 连接 池? 数据库 连接 池负责分配、管理和释放 数据库 连接 ,它允许应用程序重复使用一个现有的 数据库 连接 ,而不是再重新建立一个;释放空闲时间超过最大空闲时间的 数据库 连接 来避免因为没有释放 数据库 连接 而引起的 数据库 连接 遗漏。这项技术能明显提高对 数据库 操作的性能。 数据库 连接 池有什么好处? 数据库 连接 池技术带来的优势: 1. 资源重用 由于 数据库 连接 得到重用,避免了频繁创建、释放 连接 引起的大量性能开...
连接 查询前1000条, 连接 断开10次 数据库 ,进行查询; 长 连接 查询后1000条, 连接 1次 数据库 ,进行10次查询; 大部分测试,结果类似下边, [color=red]每次 连接 查询一次 耗时117毫秒, 一次 连接 查询多次 耗时13毫秒.[/color] [code=" php "]sort c...
正文在OOP中,一个对象只负责一个特定的任务通常是一种很好的做法。 如,你也许希望只让一个对象去访问 数据库 模式 被认为是职责 模式 ,这是因为它将创建对象的控制权委托到一个 一的访问点上。 在任何时候,应用程序中都会只有这个类仅有的一个 实例 存在。 这可以防止我们去打开 数据库 的多个 连接 ,或者不必要得使用多余的系统资源。在更加复杂的系统中,使用 模式 在维持系统程序状态的同步方面也尤其有用。所有的
当调用一个类里面的方法时候,如果该方法不是static类型的,这样我们得多次 实例 类对象然后求调用;下面看 模式 在该类里面写入如下类似代码 public class EntrantAttachmentsClass #region Instance private static readonly object LockHelper = new ob
这是我在 php 面试题中遇到的一道试题, 模式 按字面来看就是某一个类只有一个 实例 ,这样做的好处还是很大的,比如说 数据库 连接 ,我们只需要 实例 一次,不需要每次都去new了,这样极大的降低了资源的耗费。 类至少拥有以下三种公共元素:     必须拥有一个构造函数,并且必须被标记为private。     拥有一个保存类的 实例 的静态成员变量。     拥有一个访问这个 实例 的公共的静
这是我在 php 面试题中遇到的一道试题, 模式 按字面来看就是某一个类只有一个 实例 ,这样做的好处还是很大的,比如说 数据库 连接 ,我们只需要 实例 一次,不需要每次都去new了,这样极大的降低了资源的耗费。 类至少拥有以下三种公共元素: 必须拥有一个构造函数,并且必须被标记为private。 拥有一个保存类的 实例 的静态成员变量。 拥有一个访问这个 实例 的公共的静态方法 具体使用方面...
Job for nginx.service failed because the control process exited with error code. See "systemctl stat 71630 Laravel访问出错错误信息:`Warning: require(/vendor/autoload.php): failed to open stream: No such file or dire 46470