核心要點
什麼是倉庫模式?
簡單來說,它是應用程序和數據源之間中介層的一種實現。雙方都不需要了解對方即可執行各自的任務,這使得我們可以擁有一個解耦的架構,從而有助於在大型應用中進行擴展,而無需硬編碼依賴關係。
為什麼你應該關注它?
讓我們用一個例子來理解這一點。假設我們正在構建一個在線商店,銷售橙味糖果。這是一個小型商店,它保留本地庫存,所以我們不需要任何花哨的東西。店面應用程序可以只連接到數據庫,並根據現有的庫存量在線接單。由於商店只有一個供應倉庫並且運營區域有限,這將運行良好。但是,如果這家商店想要擴大其運營區域會發生什麼?商店可能想要擴展到另一個城市或全國各地,而擁有一個中央庫存系統將非常麻煩。
如果我們仍然使用數據模型,那麼我們的應用程序將是某種程度上緊密耦合的。店面應用程序需要知道它必須與之交互的每個數據源,這是一個糟糕的應用程序設計。店面應用程序的工作是允許客戶訂購糖果,應用程序不應該關心數據源,它不應該跟踪所有不同的數據源。這就是數據倉庫發揮作用的地方。根據倉庫模式,一個公共API通過接口公開,每個使用者(在本例中是我們的店面應用程序)都使用該API與數據源進行通信。使用哪個數據源或如何連接到它,這些都不關應用程序的事。應用程序只關心它獲得的數據和它發送以保存的數據。
一旦實現了倉庫模式,就可以為每個數據源創建倉庫。店面應用程序不再需要跟踪任何數據源,它只需使用倉庫API來獲取所需的數據。
它是萬能藥嗎?
不,它不是。像每個設計模式一樣,它有其優缺點。
優點:
缺點:
如何操作?
讓我們來看一個簡單的代碼示例。我將在示例中使用 Laravel 來利用其出色的依賴注入功能。如果您使用任何現代 PHP 框架,那麼它應該已經具有依賴注入/IoC 容器。實現倉庫模式需要依賴注入,因為如果沒有它,您將無法將數據倉庫綁定到倉庫接口,而整個想法是面向接口編程以避免硬編碼耦合。如果您沒有使用任何框架或您選擇的框架沒有 IoC 容器,那麼您可以使用現成的 IoC 容器(請參閱腳註)。
讓我們開始吧。首先,我們在 Composer 中設置我們的命名空間和自動加載。打開 composer.json 並為我們的命名空間添加 psr-4 自動加載(在 autoload 節點中,緊跟在 classmap 之後)。
<code class="language-json"> "autoload": { "classmap": [ "app/commands", "app/controllers", "app/models", "app/database/migrations", "app/database/seeds", "app/tests/TestCase.php" ], "psr-4": { "RocketCandy\": "app/RocketCandy" } },</code>
保存後,在終端中執行 composer dump-autoload -o
以註冊新命名空間的自動加載。在 app/RocketCandy/Repositories/OrangeCandyRepository/
中創建 OrangeCandyRepository.php
。這將是我們的倉庫接口。
<code class="language-php"><?php namespace RocketCandy\Repositories\OrangeCandyRepository; interface OrangeCandyRepository { public function get_list( $limit = 0, $skip = 0 ); public function get_detail( $candy_id = 0 ); }</code>
現在我們有了接口,我們可以創建一個倉庫。在 app/RocketCandy/Repositories/OrangeCandyRepository/
中創建 CityAOrangeCandyRepository.php
。
<code class="language-php"><?php namespace RocketCandy\Repositories\OrangeCandyRepository; class CityAOrangeCandyRepository implements OrangeCandyRepository { public function get_list( $limit = 0, $skip = 0 ) { // 查询数据源并获取糖果列表 } public function get_detail( $candy_id = 0 ) { // 查询数据源并获取糖果详情 } }</code>
為了將 CityAOrangeCandyRepository
倉庫綁定到 OrangeCandyRepository
接口,我們將利用 Laravel 的 IoC 容器。打開 app/start/global.php
並將以下內容添加到文件的末尾。
<code class="language-php">//OrangeCandyRepository App::bind( 'RocketCandy\Repositories\OrangeCandyRepository\OrangeCandyRepository', 'RocketCandy\Repositories\OrangeCandyRepository\CityAOrangeCandyRepository' );</code>
注意:我只在 global.php
中放置了 IoC 綁定以進行演示。理想情況下,這些應該放在它們自己的單獨文件中,您可以在其中放置所有IoC 綁定,然後在此處的global.php
中加載該文件,或者您可以創建服務提供程序來註冊每個IoC綁定。您可以在這裡閱讀更多信息。
現在我們可以通過接口使用倉庫了。在位於 app/controllers/
中的 CandyListingController.php
中。
<code class="language-json"> "autoload": { "classmap": [ "app/commands", "app/controllers", "app/models", "app/database/migrations", "app/database/seeds", "app/tests/TestCase.php" ], "psr-4": { "RocketCandy\": "app/RocketCandy" } },</code>
在這裡,我們將 OrangeCandyRepository
接口注入到我們的控制器中,並將它的對象引用存儲在一個類變量中,該變量現在可以被控制器中的任何函數用來查詢數據。由於我們將 OrangeCandyRepository
接口綁定到 CityAOrangeCandyRepository
倉庫,它將就像我們直接使用 CityAOrangeCandyRepository
倉庫一樣。
因此,現在,數據源的類型和種類是 CityAOrangeCandyRepository
的唯一關注點。我們的應用程序只知道 OrangeCandyRepository
接口及其公開的 API,每個實現它的倉庫都必須遵守該 API。倉庫在運行時從IoC 容器中解析,這意味著可以根據需要設置接口倉庫綁定,接口可以綁定到任何數據倉庫,而我們的應用程序無需關心數據源的變化,數據源現在可以是數據庫、 Web 服務或跨維度超數據管道。
並非所有情況都適用
正如我在倉庫模式的缺點中提到的那樣,它會增加應用程序的一定複雜性。因此,如果您正在製作一個小型應用程序,並且您沒有看到它會發展到大型應用的程度(可能需要調用多個數據源),那麼最好不要實現它,而堅持使用舊式數據模型。了解某事物與了解何時使用該事物是不同的。這是一個非常方便的設計模式,它在創建應用程序以及必須維護或擴展(或縮減)應用程序時可以節省很多麻煩,但它並非適用於所有應用程序的萬能藥。
我使用了 Laravel 特定的代碼來演示上面的實現,但是它對於任何不錯的 IoC 容器來說都相當簡單且相似。有問題?請在下面的評論中提出。
腳註:
以下是一些您可以使用的 IoC 容器庫,如果您的框架沒有或您沒有使用框架:
建議閱讀:
關於倉庫模式的常見問題
(此部分內容與原文內容高度重合,為了避免重複,此處省略。原文中的常見問題解答部分已包含了對倉庫模式的全面解釋。)
以上是存儲庫設計模式神秘的詳細內容。更多資訊請關注PHP中文網其他相關文章!