詳解 PHP 中的三大經典模式

奕鵬發表於2019-11-07

單例模式

單例模式的含義:
作為物件的建立模式,單例模式確保某一個類只有一個例項,而且自行例項化並向整個系統全域性地提供這個例項。它不會建立例項副本,而是會向單例類內部儲存的例項返回一個引用。
單例模式的三個要素: 
1.儲存類唯一例項的靜態變數。 
2.建構函式和克隆函式必須是私有的,放在外部去例項化,這樣就不存在單例模式的意義。 
3.提供一個可供外部訪問的公共靜態方法,這個方法返回該類的唯一例項。
單例模式的意義:
在 PHP 中的應用主要在於資料庫應用, 所以一個應用中會存在大量的資料庫操作, 在使用物件導向的方式開發時, 如果使用單例模式, 則可以避免大量的 new 操作消耗的資源。而不完全是對系統資源的節省, 可以避免重複例項化,因為 PHP 每次例項化一個類之後都會清理掉對應的資源,當再次使用的時候又會在重新去例項化一次。
單例模式使用的場景: 
1.資料庫操作,減少對資料路的 new 操作,從而減少記憶體資源和系統資源的消耗。 
2.配置資源的共享,在一個系統中,配置資源都是全域性的,使用單例模式也可以減少每次去讀取配置帶來的記憶體和系統資源的消耗。
程式碼演示:

<?php
class Single
{
    public static $attribute = '';
    public static $instance = '';
    private function __construct($attribute = '個人技術')
    {
        self::$attribute = $attribute;
    }
    public static function getInstance($attribute = '我是程式設計浪子走四方1')
    {
        if (!(self::$instance instanceof self)) self::$instance = new self($attribute);
        return self::$instance;
    }
}

單例模式和非單例模式的區別:

class Single {
    public function index() {
        return '';
    }
}
$single1 = new Single();
$single2 = new Single();
var_dump($single1);
var_dump($single2);
if ($single2 === $single1) {
    echo "是同一個物件";
} else {
    echo "不是同一個物件";
}
// object(Single)#1 (0) {
// }
// object(Single)#2 (0) {
// }
// 不是同一個物件
class Single2 {
    // 1.宣告一個靜態屬性,使用者儲存類的例項
    public static $instance;
    //3. 將構函式私有化,避免外部new(每new一次,就不是同一個例項)
    private function __construct() {
    }
    // 2.宣告一個靜態的公共方法,使用者外部呼叫本類的例項
    public static function getInstance() {
        if (!(self::$instance instanceof self)) {
            self::$instance = new self;
        }
        return self::$instance;
    }
    //3. 克隆函式私有化,避免外部clone(每clone一次,就不是同一個例項)
    private function __clone() {
    }
}
$singleDemo1 = Single2::getInstance();
$singleDemo2 = Single2::getInstance();
var_dump($singleDemo1->getInstance());
var_dump($singleDemo2->getInstance());
if ($singleDemo1 === $singleDemo2) {
    echo "是同一個物件";
} else {
    echo "不是同一個物件";
}
// object(Single2)#3 (0) {
// }
// object(Single2)#3 (0) {
// }
// 是同一個物件

工廠模式

工廠模式的有含義:
負責生成其他物件的方法。簡單的描述就是通過一個工廠類,去例項化其他類或者方法。
工廠模式的意義:
通過使用工廠模式,減少因為多處 new 同一個類,當這個類發生變法時,則需要多處修改。
程式碼演示:

<?php
class Factor
{
    public static function createDB()
    {
        echo '我生產了一個DB例項';
        return new DB;
    }
}
class DB
{
    public function __construct()
    {
        echo __CLASS__ . PHP_EOL;
    }
}
$db = Factor::createDB();

註冊樹模式

註冊數的含義:
註冊樹就是將多個物件註冊在一個物件池中,當我們需要使用時,直接從物件池獲取即可。

註冊數模式的優點:
單例模式解決的是如何在整個專案中建立唯一物件例項的問題,工廠模式解決的是如何不通過 new 建立例項物件的方法。 那麼註冊樹模式想解決什麼問題呢? 在考慮這個問題前,我們還是有必要考慮下前兩種模式目前面臨的侷限。 首先,單例模式建立唯一物件的過程本身還有一種判斷,即判斷物件是否存在。存在則返回物件,不存在則建立物件並返回。 每次建立例項物件都要存在這麼一層判斷。 工廠模式更多考慮的是擴充套件維護的問題。 總的來說,單例模式和工廠模式可以產生更加合理的物件。怎麼方便呼叫這些物件呢?而且在專案內如此建立的物件好像散兵遊勇一樣,不便統籌管理安排啊。因 而,註冊樹模式應運而生。不管你是通過單例模式還是工廠模式還是二者結合生成的物件,都統統給我“插到”註冊樹上。我用某個物件的時候,直接從註冊樹上取 一下就好。這和我們使用全域性變數一樣的方便實用。 而且註冊樹模式還為其他模式提供了一種非常好的想法。
程式碼演示:

<?ph
/**
 * 單例模式
 */
class Single
{
    public static $attribute = '';
    public static $instance = '';
    private function __construct($attribute = '個人技術')
    {
        self::$attribute = $attribute;
    }
    public static function getInstance($attribute = '個人技術1')
    {
        if (!(self::$instance instanceof self)) self::$instance = new self($attribute);
        return self::$instance;
    }
}
/**
 * 工廠模式
 */
class Factory
{
    public static function createObj()
    {
        return Single::getInstance('個人技術');
    }
}
/**

 * 註冊模式

 * 含義:就是將物件放在一個物件池中,使用的時候直接去物件池查詢.

 * 需要如下幾個操作:

 * 1.註冊

 * 2.存放物件池

 * 3.獲取

 * 4.銷燬

 */
Class Register
{
    // 用一個陣列來當做物件池,鍵當做物件別名,值儲存具體物件
    public static $objTree = [];
    // 將物件放在物件池
    public static function set($key, $val)
    {
        return self::$objTree[$key] = $val;
    }
    // 通過物件別名在物件池中獲取到物件別名
    public static function get($key)
    {
        return self::$objTree[$key];
    }
    // 通過物件別名將物件從物件池中登出
    public static function _unset($key)
    {
        unset(self::$objTree[$key]);
    }
}
Register::set('single', Factory::createObj());
$single = Register::get('single');
print_r($single);
echo $single::$attribute;

相關文章