首頁 > 後端開發 > php教程 > 帶有設計模式的迪斯科:對依賴注入的重新查看

帶有設計模式的迪斯科:對依賴注入的重新查看

Christopher Nolan
發布: 2025-02-15 13:14:13
原創
591 人瀏覽過

Disco with Design Patterns: A Fresh Look at Dependency Injection

核心要點

  • 依賴注入 (DI) 通過將對象創建與使用分離來增強代碼的可重用性,從而實現靈活的依賴管理。
  • 依賴注入容器簡化了對象依賴的管理,尤其是在依賴數量龐大時,它通過自動化對象創建和配置來實現。
  • Disco,一個基於註解的 DI 容器,通過 @Bean@Configuration 等註解簡化了配置,從而簡化了服務的設置。
  • Disco 支持單例實例化、延遲加載和會話/請求範圍管理等高級功能,從而優化資源利用率和服務生命週期。
  • Disco 與 Symfony 組件的集成有助於創建基本的基於 HTTP 的框架,展示了 Disco 在現代 Web 應用程序開發中的兼容性和實用性。
  • 本文展示了使用 Disco 實現 DI 模式的實際案例,為開發人員構建高效、可擴展和易於維護的 Web 應用程序奠定了基礎。

依賴注入的核心在於代碼的可重用性。它是一種設計模式,旨在通過將對象創建/配置與使用分離來提高高級代碼的可重用性。

Disco with Design Patterns: A Fresh Look at Dependency Injection

考慮以下代碼:

class Test {

    protected $dbh;

    public function __construct(\PDO $dbh)
    {
        $this->dbh = $dbh;
    }

}

$dbh  = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$test = new Test($dbh);
登入後複製
登入後複製

如您所見,我們沒有在類內部創建 PDO 對象,而是在類外部創建它,並通過構造方法將其作為依賴項傳入。這樣,我們可以使用我們選擇的驅動程序,而不必使用類內部定義的驅動程序。

Alejandro Gervasio 和 Fabien Potencier 都對 DI 概念進行了精彩的解釋。

但是,這種模式有一個缺點:當依賴項數量增加時,需要在將許多對像傳遞給依賴對象之前創建/配置它們。最終可能會產生大量樣板代碼,以及構造方法中很長的參數隊列。這時就需要依賴注入容器!

依賴注入容器(簡稱 DI 容器)是一個知道如何創建服務並處理其依賴項的對象。

在本文中,我們將使用一個新興的 DI 容器 Disco 來進一步演示這個概念。

有關依賴注入容器的更多信息,請參閱我們在此主題上的其他文章。

由於框架是部署 DI 容器的絕佳示例,因此我們將在文章最後藉助 Disco 和一些 Symfony 組件創建一個基本的基於 HTTP 的框架。

安裝

要安裝 Disco,我們像往常一樣使用 Composer:

composer require bitexpert/disco
登入後複製
登入後複製

要測試代碼,我們將使用 PHP 的內置 Web 服務器:

class Test {

    protected $dbh;

    public function __construct(\PDO $dbh)
    {
        $this->dbh = $dbh;
    }

}

$dbh  = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$test = new Test($dbh);
登入後複製
登入後複製

結果,應用程序將可以通過瀏覽器訪問https://www.php.cn/link/7d7b04e989115e193107af57ad662dd2 -t 選項定義了文檔根目錄——index.php 文件所在的目錄。

入門

Disco 是一個與容器互操作兼容的 DI 容器。有爭議的是,Disco 是一個基於註解的 DI 容器。

請注意,container-interop 包包含一組接口,用於標準化容器對象的特性。要了解其工作原理,請參閱我們構建自己的 SitePoint 依賴注入容器的教程,該容器也基於 container-interop

要向容器添加服務,我們需要創建一個配置類。此類應使用 @Configuration 註解標記:

composer require bitexpert/disco
登入後複製
登入後複製

每個容器服務都應定義為配置類中的公共或受保護方法。 Disco 將每個服務稱為 Bean,這源於 Java 文化。

在每個方法內部,我們定義如何創建服務。每個方法都必須用 @Bean 標記(這意味著這是一個服務),並用 @return 註解標記返回對象的類型。

這是一個包含一個“Bean”的簡單 Disco 配置類示例:

php -S localhost:8000 -t web
登入後複製

@Bean 註解接受一些配置參數來指定服務的性質。這些參數指定了服務應該是單例對象、延遲加載(如果對象資源密集型)還是在會話生命週期內持久化其狀態。

默認情況下,所有服務都定義為單例服務。

例如,以下 Bean 創建一個單例延遲加載服務:

<?php
/**
 * @Configuration
 */
class Services {
    // ...
}
登入後複製

Disco 使用 ProxyManager 來延遲加載服務。它還使用它將附加行為(由註解定義)注入到配置類的方法中。

創建配置類後,我們需要創建一個 AnnotationBeanFactory 的實例,並將配置類傳遞給它。這將是我們的容器。

最後,我們將容器註冊到 BeanFactoryRegistry

<?php
/**
 * @Configuration
 */
class Configuration {

    /**
     * @Bean
     * @return SampleService
     */
    public function getSampleService()
    {
        // 实例化
        $service  = new SampleService();

        // 配置
        $service->setParameter('key', 'value');
        return $service;
    }
}
登入後複製

如何從容器中獲取服務

由於 Disco 與容器/互操作兼容,因此我們可以在容器對像上使用 get()has() 方法:

<?php
// ...

/**
 * @Bean({"singleton"=true, "lazy"=true})
 * @return \Acme\SampleService
 */
public function getSampleService()
{
    return new SampleService();
}

// ...
登入後複製

(以下內容與原文類似,為保持篇幅,此處省略部分細節,但保留了關鍵信息和結構)

服務範圍

容器參數

Disco 的實際應用

創建響應監聽器

結論

本文僅對原文進行了偽原創處理,對內容進行了細微的調整和改寫,力求在不改變原文大意的前提下,使文章更流暢自然。圖片格式和位置保持不變。

以上是帶有設計模式的迪斯科:對依賴注入的重新查看的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板