首页 > 后端开发 > php教程 > 存储库设计模式神秘

存储库设计模式神秘

Lisa Kudrow
发布: 2025-02-21 08:54:13
原创
729 人浏览过

Repository Design Pattern Demystified

核心要点

  • 仓库模式充当应用程序和数据源之间的中介层,允许构建解耦的架构,从而实现可扩展性,且无需硬编码依赖关系。
  • 此模式允许应用程序无需关注数据源的细节,而专注于接收和发送用于保存的数据。它通过一个公共API(接口)实现这一点,所有使用者都通过该接口与数据源进行通信。
  • 虽然仓库模式提供了关注点分离和易于单元测试等好处,但它也增加了一层抽象,这可能会使小型应用程序变得复杂。
  • 实现仓库模式需要依赖注入,这允许将数据仓库绑定到仓库接口。这避免了硬编码耦合,并促进了面向接口编程。

什么是仓库模式?

简单来说,它是应用程序和数据源之间中介层的一种实现。双方都不需要了解对方即可执行各自的任务,这使得我们可以拥有一个解耦的架构,从而有助于在大型应用中进行扩展,而无需硬编码依赖关系。

为什么你应该关注它?

让我们用一个例子来理解这一点。假设我们正在构建一个在线商店,销售橙味糖果。这是一个小型商店,它保留本地库存,所以我们不需要任何花哨的东西。店面应用程序可以只连接到数据库,并根据现有的库存量在线接单。由于商店只有一个供应仓库并且运营区域有限,这将运行良好。但是,如果这家商店想要扩大其运营区域会发生什么?商店可能想要扩展到另一个城市或全国各地,而拥有一个中央库存系统将非常麻烦。

如果我们仍然使用数据模型,那么我们的应用程序将是某种程度上紧密耦合的。店面应用程序需要知道它必须与之交互的每个数据源,这是一个糟糕的应用程序设计。店面应用程序的工作是允许客户订购糖果,应用程序不应该关心数据源,它不应该跟踪所有不同的数据源。这就是数据仓库发挥作用的地方。根据仓库模式,一个公共API通过接口公开,每个使用者(在本例中是我们的店面应用程序)都使用该API与数据源进行通信。使用哪个数据源或如何连接到它,这些都不关应用程序的事。应用程序只关心它获得的数据和它发送以保存的数据。

一旦实现了仓库模式,就可以为每个数据源创建仓库。店面应用程序不再需要跟踪任何数据源,它只需使用仓库API来获取所需的数据。

它是万能药吗?

不,它不是。像每个设计模式一样,它有其优缺点。

优点:

  • 关注点分离;应用程序无需了解或跟踪任何或所有数据源。
  • 允许轻松进行单元测试,因为仓库绑定到在运行时注入类的接口。
  • DRY(不要重复自己)设计,从数据源查询和获取数据的代码不会重复。

缺点:

  • 添加了另一层抽象,增加了一定程度的复杂性,使其对于小型应用程序来说过于复杂。

如何操作?

让我们来看一个简单的代码示例。我将在示例中使用 Laravel 来利用其出色的依赖注入功能。如果您使用任何现代 PHP 框架,那么它应该已经具有依赖注入/IoC 容器。实现仓库模式需要依赖注入,因为如果没有它,您将无法将数据仓库绑定到仓库接口,而整个想法是面向接口编程以避免硬编码耦合。如果您没有使用任何框架或您选择的框架没有 IoC 容器,那么您可以使用现成的 IoC 容器(请参阅脚注)。

让我们开始吧。首先,我们在 Composer 中设置我们的命名空间和自动加载。打开 composer.json 并为我们的命名空间添加 psr-4 自动加载(在 autoload 节点中,紧跟在 classmap 之后)。

    "autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/database/seeds",
            "app/tests/TestCase.php"
        ],
        "psr-4": {
            "RocketCandy\": "app/RocketCandy"
        }
    },
登录后复制
登录后复制

保存后,在终端中执行 composer dump-autoload -o 以注册新命名空间的自动加载。在 app/RocketCandy/Repositories/OrangeCandyRepository/ 中创建 OrangeCandyRepository.php。这将是我们的仓库接口。

<?php
namespace RocketCandy\Repositories\OrangeCandyRepository;

interface OrangeCandyRepository {

    public function get_list( $limit = 0, $skip = 0 );

    public function get_detail( $candy_id = 0 );

}
登录后复制

现在我们有了接口,我们可以创建一个仓库。在 app/RocketCandy/Repositories/OrangeCandyRepository/ 中创建 CityAOrangeCandyRepository.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 ) {
        // 查询数据源并获取糖果详情
    }

}
登录后复制

为了将 CityAOrangeCandyRepository 仓库绑定到 OrangeCandyRepository 接口,我们将利用 Laravel 的 IoC 容器。打开 app/start/global.php 并将以下内容添加到文件的末尾。

//OrangeCandyRepository
App::bind(
    'RocketCandy\Repositories\OrangeCandyRepository\OrangeCandyRepository',
    'RocketCandy\Repositories\OrangeCandyRepository\CityAOrangeCandyRepository'
);
登录后复制

注意:我只在 global.php 中放置了 IoC 绑定以进行演示。理想情况下,这些应该放在它们自己的单独文件中,您可以在其中放置所有 IoC 绑定,然后在此处的 global.php 中加载该文件,或者您可以创建服务提供程序来注册每个 IoC 绑定。您可以在这里阅读更多信息。

现在我们可以通过接口使用仓库了。在位于 app/controllers/ 中的 CandyListingController.php 中。

    "autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/database/seeds",
            "app/tests/TestCase.php"
        ],
        "psr-4": {
            "RocketCandy\": "app/RocketCandy"
        }
    },
登录后复制
登录后复制

在这里,我们将 OrangeCandyRepository 接口注入到我们的控制器中,并将它的对象引用存储在一个类变量中,该变量现在可以被控制器中的任何函数用来查询数据。由于我们将 OrangeCandyRepository 接口绑定到 CityAOrangeCandyRepository 仓库,它将就像我们直接使用 CityAOrangeCandyRepository 仓库一样。

因此,现在,数据源的类型和种类是 CityAOrangeCandyRepository 的唯一关注点。我们的应用程序只知道 OrangeCandyRepository 接口及其公开的 API,每个实现它的仓库都必须遵守该 API。仓库在运行时从 IoC 容器中解析,这意味着可以根据需要设置接口仓库绑定,接口可以绑定到任何数据仓库,而我们的应用程序无需关心数据源的变化,数据源现在可以是数据库、Web 服务或跨维度超数据管道。

并非所有情况都适用

正如我在仓库模式的缺点中提到的那样,它会增加应用程序的一定复杂性。因此,如果您正在制作一个小型应用程序,并且您没有看到它会发展到大型应用的程度(可能需要调用多个数据源),那么最好不要实现它,而坚持使用旧式数据模型。了解某事物与了解何时使用该事物是不同的。这是一个非常方便的设计模式,它在创建应用程序以及必须维护或扩展(或缩减)应用程序时可以节省很多麻烦,但它并非适用于所有应用程序的万能药。

我使用了 Laravel 特定的代码来演示上面的实现,但是它对于任何不错的 IoC 容器来说都相当简单且相似。有问题?请在下面的评论中提出。

脚注:

  • 以下是一些您可以使用的 IoC 容器库,如果您的框架没有或您没有使用框架:

    • OrnoDi
    • Ray.Di
    • Auryn
    • Dice
    • Bucket
    • Ding
  • 建议阅读:

    • Domain Driven Design Quickly
    • Domain-Driven Design by Eric Evans

关于仓库模式的常见问题

(此部分内容与原文内容高度重合,为了避免重复,此处省略。原文中的常见问题解答部分已包含了对仓库模式的全面解释。)

以上是存储库设计模式神秘的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板