使用单例模式的出发点:
1、php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 使用单例模式, 则可以避免大量的new 操作消耗的资源。
2、如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。
3、在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。
创造单例注意:
1、一个雷只能有一个类对象(只能实例化一个对象)
2、它必须自己创建这个实例
3、它必须自行向整个系统提供这个实例
4、构造函数和克隆函数必须声明为私有的,这是为了防止外部程序 new 类从而失去单例模式的意义
5、 getInstance()方法必须声明为公有的,必须调用此方法以返回唯一实例的一个引用
6、拥有一个保存类的实例的静态成员变量
7、PHP的单例模式是相对而言的,因为PHP的解释运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收
8、拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)
另外,需要创建__clone()方法防止对象被复制(克隆)
代码如下:
1 test();
47 ?>
运用单例模式实现一个数据库类:
1link = mysql_connect($host, $username, $password);
11 $this->query("SET NAMES 'utf8'", $this->link);
12 //echo mysql_errno($this->link) . ": " . mysql_error($link). "n";
13 //var_dump($this->link);
14 return $this->link;
15 }
16 private function __clone()
17 {
18 }
19 public static function get_class_nmdb($host, $username, $password)
20 {
21 //$connector = new nmdb($host, $username, $password);
22 //return $connector;
23
24 if (FALSE == (self::$_instance instanceof self)) {
25 self::$_instance = new self($host, $username, $password);
26 }
27 return self::$_instance;
28 }
29 // 连接数据表
30 public function select_db($database)
31 {
32 $this->result = mysql_select_db($database);
33 return $this->result;
34 }
35 // 执行SQL语句
36 public function query($query)
37 {
38 return $this->result = mysql_query($query, $this->link);
39 }
40 // 将结果集保存为数组
41 public function fetch_array($fetch_array)
42 {
43 return $this->result = mysql_fetch_array($fetch_array, MYSQL_ASSOC);
44 }
45 // 获得记录数目
46 public function num_rows($query)
47 {
48 return $this->result = mysql_num_rows($query);
49 }
50 // 关闭数据库连接
51 public function close()
52 {
53 return $this->result = mysql_close($this->link);
54 }
55 }
56 $connector = DBHelper::get_class_nmdb($host, $username, $password);
57 $connector -> select_db($database);
58 ?>
也可以参考这个类实现:
1 link = @ mysql_connect($this->host, $this->user, $this->pwd) or $this->err();
21 } else {
22 $this->link = @ mysql_pconnect($this->host, $this->user, $this->pwd) or $this->err();
23 }
24 mysql_select_db($this->database) or $this->err();
25 $this->query("SET NAMES '{$this->charset}'", $this->link);
26 return $this->link;
27 }
28 /**
29 * 防止被克隆
30 *
31 */
32 private function __clone(){}
33 public static function getInstance($pconnect = false){
34 if(FALSE == (self::$_instance instanceof self)){
35 self::$_instance = new self($pconnect);
36 }
37 return self::$_instance;
38 }
39 /**
40 * 查询
41 */
42 public function query($sql, $link = '') {
43 $this->result = mysql_query($sql, $this->link) or $this->err($sql);
44 return $this->result;
45 }
46 /**
47 * 单行记录
48 */
49 public function getRow($sql, $type = MYSQL_ASSOC) {
50 $result = $this->query($sql);
51 return @ mysql_fetch_array($result, $type);
52 }
53 /**
54 * 多行记录
55 */
56 public function getRows($sql, $type = MYSQL_ASSOC) {
57 $result = $this->query($sql);
58 while ($row = @ mysql_fetch_array($result, $type)) {
59 $this->rows[] = $row;
60 }
61 return $this->rows;
62 }
63 /**
64 * 错误信息输出
65 */
66 protected function err($sql = null) {
67 //这里输出错误信息
68 echo 'error';
69 exit();
70 }
71 }
72 //用例
73 $db = mysql::getInstance();
74 $db2 = mysql::getInstance();
75 $data = $db->getRows('select * from blog');
76 //print_r($data);
77 //判断两个对象是否相等
78 if($db === $db2){
79 echo 'true';
80 }
81 ?>