Yii2設計模式——註冊樹模式

来源:https://www.cnblogs.com/minirice/archive/2018/12/20/10150129.html
-Advertisement-
Play Games

PHP註冊樹模式主要用於創建對象的時候將我們的對象與相應的變數進行綁定,從這個角度上說,Yii2的Service Locator和DI Container都用到註冊樹模式。這二者都在內部維護一個數組(key => value),value為對象或者對象定義,在獲取時通過唯一的key來獲取,如果是定義... ...


應用舉例

在Yii.php中:

<?php

class ServiceLocator extends Component
{
    //保存實例化的對象,每個對象都是單例,且有唯一string類型的ID做區分
    private $_components = [];

    //保存設置的對象或者其定義,用於實例化
    private $_definitions = [];

    //將對象ID作為ServiceLocator的屬性,可通過$serviceLocator->{ID}直接獲取
    public function __get($name)
    {
        if ($this->has($name)) {
            return $this->get($name);
        }

        return parent::__get($name);
    }

    //檢驗是否有屬性$name
    public function __isset($name)
    {
        if ($this->has($name)) {
            return true;
        }

        return parent::__isset($name);
    }

    //檢驗是否有對象$id
    public function has($id, $checkInstance = false)
    {
        return $checkInstance ? isset($this->_components[$id]) : isset($this->_definitions[$id]);
    }

    //獲取一個對象$id
    public function get($id, $throwException = true)
    {
        //已經實例化的,直接返回
        if (isset($this->_components[$id])) {
            return $this->_components[$id];
        }

        //有該對象的定義,且定義已經是一個對象,設置$_components並直接返回
        if (isset($this->_definitions[$id])) {
            $definition = $this->_definitions[$id];
            if (is_object($definition) && !$definition instanceof Closure) {
                return $this->_components[$id] = $definition;
            }

            //有定義但不是現成對象,則交給DI Container去實例化,並且設置$_components
            return $this->_components[$id] = Yii::createObject($definition);
        } elseif ($throwException) {
            throw new InvalidConfigException("Unknown component ID: $id");
        }

        return null;
    }

    //設置、存放一個對象
    public function set($id, $definition)
    {
        unset($this->_components[$id]);

        if ($definition === null) {
            unset($this->_definitions[$id]);
            return;
        }

        //如果$definition是對象或者類名或者callable,則註冊到$_definitions中
        if (is_object($definition) || is_callable($definition, true)) {
            // an object, a class name, or a PHP callable
            $this->_definitions[$id] = $definition;
        } elseif (is_array($definition)) { //如果是帶'class'的配置數組,也註冊到$_definitions中
            // a configuration array
            if (isset($definition['class'])) {
                $this->_definitions[$id] = $definition;
            } else {
                throw new InvalidConfigException("The configuration for the \"$id\" component must contain a \"class\" element.");
            }
        } else {
            throw new InvalidConfigException("Unexpected configuration type for the \"$id\" component: " . gettype($definition));
        }
    }

    //清楚註冊的對象
    public function clear($id)
    {
        unset($this->_definitions[$id], $this->_components[$id]);
    }

}

這裡用到了註冊樹。

註冊樹模式

註冊樹模式(Registry Pattern)又叫註冊模式、註冊器模式。註冊樹模式通過將對象實例註冊到一棵全局的對象樹上,需要的時候從對象樹上採摘的模式設計方法。

為什麼要採用註冊樹模式?

單例模式在整個項目中創建唯一實例的問題;工廠模式封裝了對象的創建方式(工廠方法——用一個抽象方法,抽象工廠——用一簇抽象方法),使得不必總用new關鍵詞去獲取對象;創建者模式則是分步驟的創建實例的各個部分;在Yii2中則通過依賴註入容器DI去獲取實例...

這些方法實際上都是解決一個問題——如何合理的產生一個對象。但對象既然已經產生出來了,怎麼方便的調用這些對象呢?我們在項目內部建立的對象好像散兵游勇一樣,不方便統籌管理安排啊。因而註冊數模式應運而生。不管你是何種方式產生的對象,都給我“插到”註冊樹上。我用某個對象的時候,直接從註冊樹上去取一下就好了,是不是非常方便?註冊時模式還為其他模式提供了一種非常好的想法。

代碼實現

看看註冊樹模式的實現:

class Register 
{
    //存放對象的數組
    protected static $objects;
 
    /**
     * 存放一個對象
     * @param $alias
     * @param $object
     */
    public static function set($alias,$object)
    {
        self::$objects[$alias] = $object;
    }
 
    /**
     * 獲取一個對象
     * @param $alias
     * @return mixed
     */
    public static function get($alias)
    {
        return self::$objects[$alias];
    }
 
    /**
     * 銷毀一個對象
     * @param $alias
     */
    public static function _unset($alias)
    {
        unset(self::$objects[$alias]);
 
    }
}

註冊樹模式很類似服務定位器模式,優點是集中管理,使用方便。缺點是隱藏了對象和對象之間的依賴關係。

Yii2的註冊樹模式

PHP註冊樹模式主要用於創建對象的時候將我們的對象與相應的變數進行綁定,從這個角度上說,Yii2的Service Locator和DI Container都用到註冊樹模式。這二者都在內部維護一個數組(key => value),value為對象或者對象定義,在獲取時通過唯一的key來獲取,如果是定義再去容器裡面實例化一下。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JavaScript中易混淆的DOM屬性及方法對比 ParentNode.children VS Node.prototype.childNodes :該屬性繼承自 ,返回值是一個 實例,成員是當前節點的所有 元素子節點 ,該屬性只讀,且該屬性是動態集合。 :該屬性繼承自 ,返回值是一個 實例,成員 ...
  • Array 對象方法 可以改變原數組的方法: 1) pop() 用於刪除並返回數組的最後一個元素。 語法 arrayObject.pop() 返回值 arrayObject 的最後一個元素。 2) push() 可向數組的末尾添加一個或多個元素,並返回新的長度。 語法 arrayObject.pus ...
  • 能力檢測 在編寫代碼之前先檢測特定瀏覽器的能力。例如,腳本在調用某個函數之前,可能要先檢測該函數首付存在。這種檢測方法將開發人員從考慮具體的瀏覽器類型和版本中解放出來,讓他們把註意力集中到相應的能力是否存在上。能力檢測無法精確地檢測特定的瀏覽器和版本。 怪癖檢測 怪癖實際上是瀏覽器實現中存在的bug ...
  • <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv ...
  • 楔子 最近一個項目,需要繪製雙線的效果,雙線效果表示的是軌道(類似鐵軌之類的),如下圖所示: 負責這塊功能開發的小伙,姑且稱之為L吧,最開始是通過數學計算的方式來實現這種雙線,也就是在原來的路徑的基礎上,計算出兩條路徑。但是這個過程的計算算挺複雜,而是最終實現的效果很耗性能,性能損耗估計主要在於路徑 ...
  • 一、概念 模板方法模式:在一個方法中定義一個演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變演算法結構的情況下,重新定義演算法中的某些步驟。 解析:模板方法模式用來創建一個演算法的模板。什麼是模板?模板就是一個方法。更具體地說,這個方法將演算法定義成一組步驟,其中的任何步驟都可以是抽象的, ...
  • 在一次公開課上,聽別人講過全局分散式uuid的設計,聽過twitter的snowflake的設計。也聽過,如果使用單獨的計數器服務,不可能每次都保存當前計數器到文本,自己想到應該可以每隔一些數,例如1萬次,10萬次,反正64位的空間比較大,然後保存起來,那麼就沒有每次保存,對硬碟的寫入壓力。當出現故 ...
  • 建造者模式 一:建造者概述 我們大家可能都會開小汽車,但是當你得到一輛小汽車的時候,你可以用它馳騁馬路,但是你知道它組件複雜的構造過程嗎,並不知道。而我們今天要講的建造者模式其實就是 ,`客戶端無需知道複雜對象的內部組成和裝配方式,只需要知道建造者的類型即可 一步步的創建獨立的複雜對象,不同的具體構 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...