PHP设计模式-单例模式 - Go语言中文社区

PHP设计模式-单例模式


一直以来都是在写项目却从来没有仔细分析过什么是单例模式,单例模式分为几种,单例模式有什么特点。今天随便记录一个随笔,全当是复习复习做个笔记。

单例模式要确保某个类只有一个实例,而且自动实例化并向整个系统提供实例。单例模式分为3种:饿汉单例模式、懒汉单例模式、登记式单例模式。

单例模式有3个特点:

  1. 只有一个实例
  2. 必须自行创建这个实例
  3. 必须给其他对象提供这个实例

单例模式常被应用到数据库连接,这种耗费资源的操作。类的结构分为3私1公/4私1公。下面就编写一个简单的单例模式:

 1 <?php
 2 
 3 class db {
 4 
 5     private $config = 1;
 6 
 7     //私有的静态变量,默认值为null
 8     private static $instance = null;
 9 
10     /**
11     * 私有构造方法
12     * 防止多个实例
13     */
14     private function __construct($config) {
15         echo '我是私有构造方法<br>';
16     }
17 
18     /**
19     * 私有克隆方法 
20     * 防止多个实例
21     */
22     private function __clone() {
23 
24     }
25 
26     /**
27     * 防止反序列化
28     */
29     private function __wakeup() {
30 
31     }
32 
33     /**
34     * 公有静态方法
35     * 判断$instance是否实例化,存在实例化对象就直接返回,不存在实例化对象就new实例化
36     */
37     public static function getInstance() {
38         if(is_null(self::$instance)) {
39             self::$instance = new self();
40         }
41         return self::$instance;
42     }
43 }
44 
45 $db = db::getInstance();
46 var_dump($db);
47 $db = db::getInstance();
48 var_dump($db);

执行结果:

MySQL连接单例模式

 

可以看到两次执行的句柄都一样是同一个实例。接下来把这个单例完善一下变成一个数据库连接的单例模式:

  1 <?php
  2 
  3 class db {
  4 
  5     //私有link变量
  6     private $link;
  7 
  8     private $config = [
  9         'host' => 'localhost',
 10         'username' => 'root',
 11         'password' => 'root',
 12         'databases' => '',
 13         'port' => 3306,
 14         'conding' => 'utf8'
 15     ];
 16 
 17 
 18     //私有的静态变量,默认值为null
 19     private static $instance = null;
 20 
 21     /**
 22     * 私有构造方法
 23     * 防止多个实例
 24     * array $config 数据库配置
 25     */
 26     private function __construct($config) {
 27         //判断$config配置是否设置,并且是数组
 28         if(isset($config) && is_array($config)) {
 29             //存在配置,和默认配置合并,用新的配置替换默认配置
 30             $this->config = array_merge($this->config, $config);
 31         }
 32         //创建数据库连接
 33         $this->link = mysqli_connect($this->config['host'], $this->config['username'], $this->config['password'], $this->config['databases'], $this->config['port']);
 34 
 35         //输出连接错误
 36         $this->connect_errno();
 37 
 38         if($this->config['databases']) {
 39             $conding = $this->config['conding'];
 40             $this->query("SET NAMES '{$condig}'");
 41         }
 42         
 43         return $this->link;
 44     }
 45 
 46     /**
 47     * 私有克隆方法 
 48     * 防止多个实例
 49     */
 50     private function __clone() {
 51 
 52     }
 53 
 54     /**
 55     * 防止反序列化
 56     */
 57     private function __wakeup() {
 58 
 59     }
 60 
 61     /**
 62     * 公有静态方法
 63     * 判断$instance是否实例化,存在实例化对象就直接返回,不存在实例化对象就new实例化
 64     * array $config 数据库配置
 65     */
 66     public static function getInstance($config) {
 67         //判断变量$instance是否存在实例化对象,不存在
 68         if(is_null(self::$instance)) {
 69             //自动实例化,给构建方法传$config配置
 70             self::$instance = new self($config);
 71         }
 72         //返回$instance实例化对象
 73         return self::$instance;
 74     }
 75 
 76     /**
 77     * 执行sql
 78     * $query sql语句
 79     */
 80     public function query($query) {
 81         $this->result = mysqli_query($this->link, $query);
 82         return $this->result;
 83     }
 84 
 85     /**
 86     * 选择数据库
 87     * string $dbname 数据库名称
 88     */
 89     public function select_db($dbname) {
 90         $this->result = mysqli_select_db($this->link, $dbname);
 91         $conding = $this->config['conding'];
 92         $this->query("SET NAMES '{$condig}'");
 93         return $this->result;
 94     }
 95 
 96     /**
 97     * 查询一条或多条数据
 98     * string $sql sql语句
 99     * MYSQLI_NUM、MYSQLI_ASSOC、MYSQLI_BOTH
100     */
101     public function fetch_array($sql, $type = MYSQLI_BOTH) {
102         $result = $this->query($sql);
103         $rows = mysqli_fetch_array($result, $type);
104         if($this->num_rows($result) > 1) {
105             while($rows) {
106                 $this->rows[] = $rows;
107             }
108         } else {
109             $this->rows = $rows;
110         }
111         return $this->rows;
112     }
113 
114     public function num_rows($result) {
115         $this->result = mysqli_num_rows($result);
116         return $this->result;
117     }
118 
119     /**
120     * 输出连接错误
121     */
122     private function connect_errno() {
123         if(mysqli_connect_errno($this->link)) {
124             echo 'MySQL数据库连接失败,错误代码ERROR:' . mysqli_connect_errno() . '<br>';
125         }
126     }
127 
128     /**
129     * 关闭数据库连接
130     */
131     public function close() {
132         $this->result = mysqli_close($this->link);
133         return $this->result;
134     }
135 
136 
137 }
138 
139 $config = [
140     'host' => '172.17.0.2',
141     'username' => 'root',
142     'password' => 'cuiyuanxin66666',
143     // 'databases' => 'nndb'
144 ];
145 $db = db::getInstance($config);
146 $db1 = db::getInstance($config);
147 //判断两个实例对象是否一致
148 if($db === $db1) {
149     echo '一致';
150     echo '<br>';
151 } else {
152     echo '不一致';
153     echo '<br>';
154 }
155 //切换数据库hkxy
156 $db->select_db('hkxy');
157 $sql = 'select * from qii_admin_menu limit 1';
158 $rows = $db->fetch_array($sql, MYSQLI_ASSOC);
159 var_dump($db);
160 echo '<br>-----------------------------------------<br>';
161 var_dump($rows);
162 echo '<br>-----------------------------------------<br>';
163 $db->select_db('nndb');
164 $sql = 'select * from niuniu_user limit 1';
165 $rows = $db->fetch_array($sql, MYSQLI_ASSOC);
166 var_dump($rows);

经过改造一个连接数据库的单例模式就写完了,看一下执行结果:

MySQL连接单例模式

通过代码来看两个实例对象完全一样。

源代码已上传GitHub:https://github.com/cuiyuanxin/php-demo/blob/master/db.php

纯手打笔记,如有错误请评论提出,谢谢。

版权声明:本文来源博客园,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://www.cnblogs.com/cuiyuanxin/p/10421440.html
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-11-17 00:15:39
  • 阅读 ( 1482 )
  • 分类:设计模式

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢