PHP單例設計模式與工廠設計模式
單例設計模式
概念
一個類只能創建一個實例對象,不管用什麼方法都無法創建第2個對象, 比如,數據庫類
單例設計模式的要求(三私一公)
一私:私有的靜態的保存對象的屬性
一私:私有的構造方法,阻止類外new對象
一私:私有的克隆方法,阻止類外clone對象
一公:公共的靜態的創建對象的方法
單例設計模式的核心代碼
<?php
//單例設計模式的核心代碼
class Db
{
//私有的靜態的保存對象的屬性
private static $obj = null;
//私有的構造方法:阻止類外new 對象
private function __construct()
{
}
//私有的克隆方法:阻止類外clone對象
private function __clone()
{
// TODO: Implement __clone() method.
}
//公共的靜態的創建對象的方法
public static function getInstace()
{
//判斷當前對象是否存在
if(!self::$obj instanceof self) //instance 判斷一個對象是不是某個類的對象
{
//如果對象不存在,創建並保存它
self::$obj = new self();
}
//返回對象
return self::$obj;
}
}
//創建數據庫類的對象
$db1 = Db::getInstace();
$db2 = Db::getInstace();
var_dump($db1,$db2);
單例設計模式的實例:數據庫類 Db.class.php
<?php
//單例設計模式的核心代碼
//數據庫模塊
class Db
{
//私有的靜態的保存對象的屬性
private static $obj = null;
//私有的數據庫配置信息
private $db_host; //主機名
private $db_user; //用戶名
private $db_pass; //密碼
private $db_name; //數據庫名
private $charset; //字符集
private $link; //連接對象
//私有的構造方法:阻止類外new 對象
private function __construct($config=array())
{
$this->db_host = $config['db_host'];
$this->db_user = $config['db_user'];
$this->db_pass = $config['db_pass'];
$this->db_name = $config['db_name'];
$this->charset = $config['charset'];
$this->connectDb();//連接數據庫
$this->selectDb();//選擇數據庫
$this->setCharset();//設置字符集
}
//私有的克隆方法:阻止類外clone對象
private function __clone()
{
// TODO: Implement __clone() method.
}
//公共的靜態的創建對象的方法
public static function getInstace($config)
{
//判斷當前對象是否存在
if(!self::$obj instanceof self) //instance 判斷一個對象是不是某個類的對象
{
//如果對象不存在,創建並保存它
self::$obj = new self($config);
}
//返回對象
return self::$obj;
}
//私有的鏈接MySQL服務器方法
private function connectDb()
{
if (!$this->link = @mysqli_connect($this->db_host,$this->db_user,$this->db_pass))
{
echo "連接數據庫失敗";
die();
}
}
//私有的選擇數據庫的方法
private function selectDb()
{
if(!mysqli_select_db($this->link,$this->db_name))
{
echo "選擇數據庫{$this->db_name}失敗!";
die();
}
}
//私有的設置字符集
private function setCharset()
{
mysqli_set_charset($this->link,$this->charset);
}
//公共的執行SQL語句的方法:insert update delete set drop
//執行成功返回true,執行失敗返回false
public function exec($sql)
{
//例如:update student set salary = salary+500 where id=5
//將sql語句轉化成全小寫
$sql = strtolower($sql);
//判斷是不是select語句
if(substr($sql,0,6)=='select')
{
echo "不能執行select語句";
die();
}
//返回執行結果,爲bool值
return mysqli_query($this->link,$sql);
}
//私有的執行sql語句的方法:select
//執行成功返回結果集對象,失敗返回false
private function query($sql)
{
//例如 select *from student
//將sql語句轉化成全小寫
$sql = strtolower($sql);
//判斷是不是select語句
if(substr($sql,0,6)!='select')
{
echo "不能執行非select語句";
die();
}
//返回執行結果集對象,後續數據取出,處理,送給前端
return mysqli_query($this->link,$sql);
}
//公共的獲取單行數據的方法
public function fetchOne($sql,$type=3)
{
//執行Sql語句,並返回結果集對象
$result = $this->query($sql);
//定義返回數組類型的常量
$types = array(
1 => MYSQLI_NUM,
2 => MYSQLI_BOTH,
3 => MYSQLI_ASSOC,
);
//返回一維數組
return mysqli_fetch_array($result,$types[$type]);
}
//公共的獲取多行數據的方法
public function fetchAll($sql,$type=3)
{
//執行sql語句,並返回結果集對象
$result = $this->query($sql);
//定義返回數組類型的常量
$types = array(
1 => MYSQLI_NUM,
2 => MYSQLI_BOTH,
3 => MYSQLI_ASSOC,
);
//返回二維數組
return mysqli_fetch_all($result,$types[$type]);
}
//獲取記錄數
public function rowCount($sql)
{
//執行sql語句,返回結果幾對象
$result = $this->query($sql);
//返回記錄數
return mysqli_num_rows($result);
}
//公共的析構方法
public function __destruct()
{
// TODO: Implement __destruct() method.
mysqli_close($this->link);//斷開mysql連接
}
}
$arr = array(
'db_host'=>'localhost',
'db_user'=>'root',
'db_pass'=>'135262',
'db_name'=>'php_test',
'charset'=>'utf8'
);
工廠設計模式
概念
根據不同的類名參數,返回不同類的對象
工廠模式,就是生產各種不同類的對象
工廠模式:改變了在類外使用new關鍵字創建對象的方式,改成了在工廠類中創建
類的對象
在類的外部我們無法控制類的行爲,但在類內部自己可以控制類的行爲
工廠設計模式的要求
一般情況下,定義一個工廠類
工廠類中的方法,應該就是公共的靜態的方法
該方法功能:就是根據傳遞的不同參數,去創建不同的類實例
工廠設計模式的核心代碼
Shape.class.php
<?php
//定義形狀接口
interface Shape
{
//繪製方法
public function draw();
}
Rectangle.class.php
<?php
//定義矩形類,並實現形狀接口
class Rectangle implements Shape
{
//重寫draw()方法
public function draw()
{
// TODO: Implement draw() method.
echo "正在繪製矩形";
}
}
Circle.class.php
<?php
class Circle implements Shape
{
//重寫draw()方法
public function draw()
{
// TODO: Implement draw() method.
echo "正在繪製圓形";
}
}
Line.class.php
<?php
//定義線型類,並實現形狀接口
class Line implements Shape
{
//重寫draw()方法
public function draw()
{
// TODO: Implement draw() method.
echo "正在繪製線條";
}
}
Factory.class.php
<?php
//定義形狀工廠類:生產不同形狀對象的工廠
class Factory
{
//公共的靜態的創建不同類對象的方法
public static function getInstance($className)
{
//根據傳遞的不同類名參數,返回不同類對象
switch ($className)
{
case "Rectangle":
return new Rectangle();
break;
case "Circle":
return new Circle();
break;
case "Line":
return new Line();
break;
default:
return null;
}
}
}
app.php
<?php
//類的自動加載
spl_autoload_register(function ($className){
//構建類文件的路徑
$filename = "$className.class.php";
//如果類文件存在,則包含
if (file_exists($filename)) require_once ($filename);
});
//創建矩形對象
$rectangle = Factory::getInstance("Rectangle");
$rectangle->draw();
總結
單例模式會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例,
可以有效限制實例化對象
單例設計模式比較適用於類似數據庫類這種具有統一性行爲的類
工廠模式相對於後期擴展來說比較容易,也就是有更好的維護性和擴展性