PHP單例設計模式與工廠設計模式

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();

總結

單例模式會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例,
	可以有效限制實例化對象
單例設計模式比較適用於類似數據庫類這種具有統一性行爲的類
工廠模式相對於後期擴展來說比較容易,也就是有更好的維護性和擴展性
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章