根据马可(Marco)的Pivetta思想,用this表示,这个old question
还有我对an other question的回答

我在问自己关于在Zend Framework 2应用程序中使用我们的服务的更好方法。

实际上,我们可以将ServiceLocatorAwareInterfaceServiceLocatorAwareTrait结合使用。
考虑到In ZF3 service locator will be removed in controller的事实,他们可能还会删除此接口(interface),或者建议人们不使用它,这是有道理的。

我了解如何构建我们的服务的唯一方法是:



问题是 :

一些项目是如此之大,以至于您要么:

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

  • 有关服务中可能需要的一些示例:
  • 取回formManager(您不能在 Controller 中调用它)
  • 在通过AJAX和JSON响应将HTML字符串返回到 View 之前,您可能需要获取ViewRenderer来呈现模板。
  • 您可能需要找回ZF2想要提供的翻译器或所有服务
  • 获取您的实体管理器,如果您有多个数据库,请在此处添加计数
  • 获取其他服务,例如MailService,ExportService,ImportService等...
  • 如果必须加载特定服务,则取决于客户端(BtoB中的多客户端网站...添加某些服务,因为您无法加载|调用AbstractFactory)

  • 也许对于某些观点,可以通过我不知道的技巧来解决。



    从评论中编辑

    为了说明我的观点,我粘贴了我的构造函数之一:
    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();
    }
    

    如您所见,ToolboxService是一个本身具有多个依赖关系的对象。该服务位于我的“应用程序”文件夹中,几乎在所有地方。
    我有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);
                }
    

    最佳答案

    假设您要注入(inject)ServiceLocator实例。无法保证ServiceLocator实际上持有您的硬依赖性,从而破坏了DI模式。使用构造函数依赖项注入(inject)时,请确保所需的所有服务都确实可用。否则,服务的构建将完全失败。

    当使用ServiceLocator时,您将最终进入实例化的服务类,在该服务类中,可以通过ServiceLocator提供或不提供硬依赖关系。这意味着您必须编写所有种类的其他逻辑(检查依赖关系,引发异常),以防在您寻求ServiceLocator实例时无法从ServiceLocator实例解析该依赖关系。编写所有这些代码可能会比注入(inject)15个依赖项花费更多的工作,并且最重要的是,整个服务中的逻辑将变得困惑不堪。

    另外,您仍然需要添加所有的setter和getter方法,以便能够从ServiceLocator获得服务并使其可测试。

    恕我直言,注入(inject)15个依赖项比注入(inject)ojit_code实例的代码更少,维护起来更容易。

    10-08 07:16