当前位置: 首页 > 知识库问答 >
问题:

ServiceLocator,让我们在ZF2环境中思考一下

闾丘坚诚
2023-03-14

根据马可·皮维塔的想法,这个老问题和我对另一个问题的回答

我在询问自己如何更好地在Zend Framework 2应用程序中使用我们的服务。

实际上,我们可以将ServiceLocatorAware InterfaceServiceLocatorAware Trait结合使用。事实上,在ZF3中,服务定位器将在控制器中被删除。他们可能也会删除这个接口,或者建议人们不要使用它,这是有意义的。

我认为构建我们的服务的唯一方式是:

不要在您的服务中使用ServiceLocator,请使用Dependancy注入。

问题是 __________:

有些项目是如此之大,以至于你有:

  • 一个工作流的 15 个服务的类。
  • 具有 15 个依赖项的服务类。
  • 选择你的噩梦...

您在服务中可能需要的一些示例:

  • 取回formManager(不能在控制器中调用它)
  • 在通过AJAX和JSON响应将超文本标记语言字符串返回视图之前,您可能需要让ViewRenader渲染模板;
  • 您可能需要取回ZF2提供的翻译或您想要的所有服务
  • 获取您的实体管理器,如果您有多个数据库,请在此处添加count
  • 获取其他服务,如邮件服务、导出服务、导入服务等…
  • 如果您必须加载特定服务,则取决于客户端(BtoB中的多客户端网站…添加一些服务,因为您无法加载|调用AbstractFactory)

也许对于其中的一些点,它们可以通过一个我不知道的技巧来解决。

我的问题是:

为一个服务提供 15 个或更多依赖项并放弃服务定位器(在控制器中,以及在服务中)是否是一种很好的做法?

从评论编辑

为了说明我的观点,我粘贴了我的一个构造函数

public function __construct(
    ToolboxService $toolboxService,
    EntityService $entityService,
    UserService $userService,
    ItemService $itemService,
    CriteriaService $criteriaService,
    Import $import,
    Export $export,
    PhpRenderer $renderer
) {
    $this->toolboxService = $toolboxService;
    $this->entityService = $entityService;
    $this->userService = $userService;
    $this->emOld = $this->toolboxService->getEmOld();
    $this->emNew = $this->toolboxService->getEmNew();
    $this->serviceLocator = $this->toolboxService->getServiceLocator();
    $this->itemService = $itemService;
    $this->criteriaService = $criteriaService;
    $this->import = $import;
    $this->export = $export;
    $this->renderer = $renderer;
    $this->formManager = $this->toolboxService->getFormManager();
}

如您所见,工具箱服务是一个具有多个依赖项的对象。此服务位于我的“应用程序”文件夹中,几乎无处不在。我有2个实体管理器(连接到2个数据库,但也许很快,我需要第三个...)

您可以看到,我通过依赖关系使用serviceLocator,因此该服务不实现ServiceLocatorAwareInterface。如果我不使用它,我会为我的AbstractFactory电话

// Distribute somes orders depends on Clients
$distributionClass = $this->serviceLocator->get(ucfirst($param->type));
            if ($distributionClass instanceof DistributeInterface) {
                $distributionClass->distribute($orders, $key);
            } else {
                throw new \RuntimeException("invalid_type_provided", 1);
            }

共有1个答案

梁丘俊人
2023-03-14

假设您将注入ServiceLocator实例。不能保证ServiceLocator实际上保存了您的硬依赖项,从而打破了DI模式。当使用构造函数依赖注入时,您可以确保所需的所有服务都确实可用。否则,服务的构造将失败。

使用服务定位器时,您最终将进入一个实例化的服务类,其中硬依赖项可能通过服务定位器提供,也可能不可用。这意味着您必须编写所有类型的附加逻辑(检查依赖项,抛出异常),以防依赖项无法在您请求时从 ServiceLocator 实例解析。编写所有这些代码可能会比注入 15 个依赖项要多得多,最重要的是,逻辑将在整个服务中变得混乱。

此外,您还需要添加所有的setter和getter方法,以便能够从< code>ServiceLocator获取您的服务,并使您的服务可测试。

IMHO注入15个依赖项的代码比注入ServiceLocator实例更少,更容易维护。

 类似资料:
  • 非常非常重要 当前最通用的编码UTF-8,同时也避免一堆乱码问题. 本教程一概使用UTF-8编码. 用 Notepad++或其他非记事本的文本编辑器,打开nutzbook/eclipse/eclipse.ini文件 在末尾加入一句 -Dfile.encoding=UTF-8 效果如下 保存并重启Eclipse

  • 问题内容: 我在EC2竞价型实例上运行R,并且需要R终止实例并在脚本运行后取消竞价请求。 为此,我在环境变量中设置了“请求ID” ,我的计划是在脚本准备好后将以下代码简单地调用到R中 我遇到的问题是R无法“看到”我从外部R 键入时看到的相同环境变量,因此该命令无法正常工作。 我已经检查了一下,如果我将环境变量设置为R,就可以看到这些变量,但这是另一个问题。由于这些变量是动态的(每次创建竞价型实例时

  • 我需要一些帮助在集合中思考。我有两个有效的查询。他们给我SET1和SET2。现在,对于SET1中的每一行,我需要应用SET2中的不同日期来获得最终结果SET3。 我们公司为经常错过约会的客户提供服务。我有一个复杂的查询,它会导致一组客户在过去六个月内错过了约会(“没有预约”),这个查询统计了该组中每个客户没有预约的次数。 SET2现在,我需要提高赌注,并显示自上次与客户的主要临床医生预约以来,有多

  • 我在CentOS 5、Apache 2.2和PHP 5.4的非常旧的虚拟机上有ZF2应用程序。我尝试在同一个VM上设置不同的环境。因此,我们有: 1)3个文件夹: 使用几乎相同的源代码(git存储库的不同分支)。 2)3个子域: 3)httpd.conf: 为了确保它正常工作,我在每个文件夹的主\索引视图中添加了两行代码。 对于开发人员: 对于qa: 对于prod: 重启httpd服务后: > 如

  • New in version 1.1. 你完全有可能遇到一些更新包需要通过proxy才能正常获取,或者甚至一部分包需要通过proxy升级而另外一部分包则不需要通过proxy.或者可能你的某个脚本需要调用某个环境变量才能正常运行. Ansible 使用 ‘environment’ 关键字对于环境部署的配置非常简单容易,下面是一个使用案例: - hosts: all remote_user: ro

  • 我从Let's Encrypt获得了有效的https证书,但将其提供给vert时存在信任问题。x版本3.6.2 我用apache测试了cert,没问题,但是如果我试图用wget到达https vert. x服务器实例,我会得到: $wgethttps://www.myhost.mydomain/json/read/all-languages -2019-01-22 10:30:56--https: