PHP設計模式-單例模式
一直以來都是在寫專案卻從來沒有仔細分析過什麼是單例模式,單例模式分為幾種,單例模式有什麼特點。今天隨便記錄一個隨筆,全當是複習複習做個筆記。
單例模式要確保某個類只有一個例項,而且自動例項化並向整個系統提供例項。單例模式分為3種:餓漢單例模式、懶漢單例模式、登記式單例模式。
單例模式有3個特點:
- 只有一個例項
- 必須自行建立這個例項
- 必須給其他物件提供這個例項
單例模式常被應用到資料庫連線,這種耗費資源的操作。類的結構分為3私1公/4私1公。下面就編寫一個簡單的單例模式:
1 <?php 2 3 class db { 4 5private $config = 1; 6 7//私有的靜態變數,預設值為null 8private static $instance = null; 9 10/** 11* 私有構造方法 12* 防止多個例項 13*/ 14private function __construct($config) { 15echo '我是私有構造方法<br>'; 16} 17 18/** 19* 私有克隆方法 20* 防止多個例項 21*/ 22private function __clone() { 23 24} 25 26/** 27* 防止反序列化 28*/ 29private function __wakeup() { 30 31} 32 33/** 34* 公有靜態方法 35* 判斷$instance是否例項化,存在例項化物件就直接返回,不存在例項化物件就new例項化 36*/ 37public static function getInstance() { 38if(is_null(self::$instance)) { 39self::$instance = new self(); 40} 41return self::$instance; 42} 43 } 44 45 $db = db::getInstance(); 46 var_dump($db); 47 $db = db::getInstance(); 48 var_dump($db);
執行結果:
可以看到兩次執行的控制代碼都一樣是同一個例項。接下來把這個單例完善一下變成一個數據庫連線的單例模式:
1 <?php 2 3 class db { 4 5//私有link變數 6private $link; 7 8private $config = [ 9'host' => 'localhost', 10'username' => 'root', 11'password' => 'root', 12'databases' => '', 13'port' => 3306, 14'conding' => 'utf8' 15]; 16 17 18//私有的靜態變數,預設值為null 19private static $instance = null; 20 21/** 22* 私有構造方法 23* 防止多個例項 24* array $config 資料庫配置 25*/ 26private function __construct($config) { 27//判斷$config配置是否設定,並且是陣列 28if(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 38if($this->config['databases']) { 39$conding = $this->config['conding']; 40$this->query("SET NAMES '{$condig}'"); 41} 42 43return $this->link; 44} 45 46/** 47* 私有克隆方法 48* 防止多個例項 49*/ 50private function __clone() { 51 52} 53 54/** 55* 防止反序列化 56*/ 57private function __wakeup() { 58 59} 60 61/** 62* 公有靜態方法 63* 判斷$instance是否例項化,存在例項化物件就直接返回,不存在例項化物件就new例項化 64* array $config 資料庫配置 65*/ 66public static function getInstance($config) { 67//判斷變數$instance是否存在例項化物件,不存在 68if(is_null(self::$instance)) { 69//自動例項化,給構建方法傳$config配置 70self::$instance = new self($config); 71} 72//返回$instance例項化物件 73return self::$instance; 74} 75 76/** 77* 執行sql 78* $query sql語句 79*/ 80public function query($query) { 81$this->result = mysqli_query($this->link, $query); 82return $this->result; 83} 84 85/** 86* 選擇資料庫 87* string $dbname 資料庫名稱 88*/ 89public function select_db($dbname) { 90$this->result = mysqli_select_db($this->link, $dbname); 91$conding = $this->config['conding']; 92$this->query("SET NAMES '{$condig}'"); 93return $this->result; 94} 95 96/** 97* 查詢一條或多條資料 98* string $sql sql語句 99* MYSQLI_NUM、MYSQLI_ASSOC、MYSQLI_BOTH 100*/ 101public function fetch_array($sql, $type = MYSQLI_BOTH) { 102$result = $this->query($sql); 103$rows = mysqli_fetch_array($result, $type); 104if($this->num_rows($result) > 1) { 105while($rows) { 106$this->rows[] = $rows; 107} 108} else { 109$this->rows = $rows; 110} 111return $this->rows; 112} 113 114public function num_rows($result) { 115$this->result = mysqli_num_rows($result); 116return $this->result; 117} 118 119/** 120* 輸出連線錯誤 121*/ 122private function connect_errno() { 123if(mysqli_connect_errno($this->link)) { 124echo 'MySQL資料庫連線失敗,錯誤程式碼ERROR:' . mysqli_connect_errno() . '<br>'; 125} 126} 127 128/** 129* 關閉資料庫連線 130*/ 131public function close() { 132$this->result = mysqli_close($this->link); 133return $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) { 149echo '一致'; 150echo '<br>'; 151 } else { 152echo '不一致'; 153echo '<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);
經過改造一個連線資料庫的單例模式就寫完了,看一下執行結果:
通過程式碼來看兩個例項物件完全一樣。