【问题标题】:Symfony - Is it better to use a service factory or a service configurator?Symfony - 使用服务工厂还是服务配置器更好?
【发布时间】:2017-03-27 14:26:45
【问题描述】:

似乎有两种方法可以在 Symfony 中动态实例化服务:

这两种方法似乎都是最新的。检查问题和变更日志并没有给我更多信息,说明哪种方法最常见或哪种方法被认为是最佳实践。

那么,我应该使用服务工厂而不是服务配置器还是服务配置器而不是工厂?为什么?哪个是最近的?

非常感谢!

【问题讨论】:

  • 根据其他几个人的要求,发布有关您的特定用例的更多信息。特别要区分“编译时”配置和基于请求的“运行时”配置。

标签: php symfony dependency-injection factory


【解决方案1】:

基本上,它们不一样:工厂用于创建服务,配置器用于在创建后对其进行配置。

当您需要实例化服务(并且可能注入其他服务或参数)时,请使用标准服务配置文件(即:services.yml)。

当您需要控制服务实例化时使用工厂。

当您需要在创建后配置服务并且希望将服务定义与服务配置分开时,请使用服务配置器。

【讨论】:

  • 你有一个真实的例子来说明何时使用服务配置器吗?基本上,我的服务参数之一是在运行时动态定义的,通过文件系统“找到”信息。 stackoverflow.com/questions/23156907/…
  • @Hussard 如果你阅读了你链接的文档,你会发现真正的用例
【解决方案2】:

在一些特殊情况下使用服务工厂而不是服务配置器是更好的决定:

1) 为旧的 PHP 类创建服务定义,因为在过去,创建逻辑通常隐藏在静态工厂类中 例如,Doctrine_Core::getTable()

public static function getTable($componentName)
{
    return Doctrine_Manager::getInstance()->getConnectionForComponent($componentName)->getTable($componentName);
}

https://github.com/doctrine/doctrine1/blob/master/lib/Doctrine/Core.php

2) 使用工厂服务和检索服务的方法的一个特别好的例子是 以 Doctrine 存储库为例。当你需要一个时,你通常会注入一个实体管理器作为 构造函数参数,然后检索特定存储库:

use Doctrine\ORM\EntityManager;

class SomeClass
{
    public function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function doSomething()
    {
        $repository = $this->entityManager->getRepository('User');
    }
}

但是使用工厂服务和方法,您可以直接注入正确的存储库本身:

class SomeClass
{
    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }
}

...

<service id="some_service" class="SomeClass">
    <argument type="user_repository" />
</service>

...

<service id="user_repository" class="UserRepository"
   factory-service="entity_manager" factory-method="getRepository">
   <argument>User</argument>
</service>

通过查看 SomeClass 的构造函数参数,很明显它需要一个 用户存储库,它比前面的示例更具体,更具交流性 SomeClass 需要一个 EntityManager 。除了使类本身更清洁之外,它还将使 当您为此编写单元测试时,为存储库创建一个替代对象要容易得多 班级。无需为实体管理器和存储库创建模拟,您只需 为存储库本身创建一个。

使用服务工厂的缺点是(根据 Matthias):

我反对使用静态工厂方法的工厂类是 静态代码是全局代码,执行该代码可能有副作用 无法隔离的效果(例如在测试场景中)。 此外,这种静态工厂方法的任何依赖都必须通过 定义静态本身,这也非常不利于隔离和 防止您自己替换(部分)创建逻辑 代码。工厂对象(或工厂服务)稍好一些。 然而,对它们的需求很可能指向某种设计 问题。服务不应该需要工厂,因为它将被创建 仅以预先确定的(和确定的)方式进行一次,从那时起 可以被任何其他对象完全重用。唯一的事情是 关于服务的动态,应该是方法的参数 是其公共接口的一部分

【讨论】:

  • 你有一个真实的例子来说明何时使用服务配置器吗?基本上,我的服务参数之一是在运行时动态定义的,通过文件系统“找到”信息。 stackoverflow.com/questions/23156907/…
  • 你能用你的动态服务的代码更新你原来的问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-14
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
  • 2015-10-31
相关资源
最近更新 更多