简体   繁体   English

Symfony-使用服务工厂或服务配置程序会更好吗?

[英]Symfony - Is it better to use a service factory or a service configurator?

There seems to be two ways to dynamically instantiate a service in Symfony: 在Symfony中,似乎有两种方法可以动态实例化服务:

Both methods seem to be current. 两种方法似乎都是最新的。 Inspecting the issues and changelog didn't give me any more informations on which is the most common or which method is considered best practice. 检查问题和变更日志并没有给我更多有关哪种方法最常见或哪种方法被视为最佳实践的信息。

So, should I be using service factory over service configurator or service configurator over factory? 因此,我应该在服务配置器上使用服务工厂,还是在工厂使用服务配置器? Why and which is the more recent? 为什么以及最近的是哪个?

Thanks a lot! 非常感谢!

Basically, their not the same: a factory is used to create the service, the configurator is used to configure it after its creation. 基本上,它们是不一样的:使用工厂创建服务,使用配置程序在创建服务后对其进行配置。

Use standard service configuration file (ie.: services.yml ) when you need to instantiate a service (and maybe inject other services or parameters). 当您需要实例化服务(并可能注入其他服务或参数)时,请使用标准服务配置文件(即: services.yml )。

Use the factory when you need to take control over service instantiation. 需要控制服务实例化时,请使用工厂。

Use service configurator when you need to configure your service, after creation, and you want to keep service definition separate from service configuration. 创建服务后需要配置服务时,并且要将服务定义与服务配置分开时,请使用服务配置器。

Using service factory over service configurator is better decision in a few special cases: 在某些特殊情况下,最好通过服务配置器使用服务工厂:

1) Creating service definitions for older PHP classes since, in the past, creation logic was often hidden inside static factory classes For example, Doctrine_Core::getTable() 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 https://github.com/doctrine/doctrine1/blob/master/lib/Doctrine/Core.php

2) One particularly nice example of using a factory service and method for retrieving a service is the case of a Doctrine repository. 2)使用工厂服务和方法检索服务的一个特别好的例子是Doctrine存储库。 When you need one, you would normally inject an entity manager as a constructor argument and later retrieve a specific repository: 当需要时,通常将实体管理器作为构造函数参数注入,然后检索特定的存储库:

use Doctrine\ORM\EntityManager;

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

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

But using a factory service and method you could directly inject the correct repository itself: 但是,使用工厂服务和方法,您可以直接注入正确的存储库本身:

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>

By looking at the constructor arguments of SomeClass it is immediately clear that it needs a User repository, which is much more specific and communicative than the earlier example in which SomeClass needed an EntityManager . 通过查看SomeClass的构造函数参数,可以很明显地看出它需要一个User信息库,它比之前的SomeClass需要EntityManager的示例更加具体和可通信。 Besides making the class itself much cleaner, it will also make it much easier to create a stand-in object for the repository when you are writing a unit test for this class. 除了使类本身更加整洁外,在编写此类的单元测试时,还将使为存储库创建替代对象变得更加容易。 Instead of creating a mock for both the entity manager and the repository, you only have to create one for the repository itself. 无需为实体管理器和存储库创建模拟,只需为存储库本身创建一个模拟即可。

Drawbacks of using service factory are (according to Matthias): 使用服务工厂的缺点是(根据Matthias的说法):

My objection to factory classes with static factory methods is that static code is global code and that executing that code may have side effects that can not be isolated (for instance in a test scenario). 我反对使用静态工厂方法的工厂类,因为静态代码是全局代码,执行该代码可能会产生无法隔离的副作用(例如,在测试场景中)。 Besides, any dependency of such a static factory method has to be by definition static itself, which is also really bad for isolation and prevents you from replacing (part of) the creation logic by your own code. 此外,此类静态工厂方法的任何依赖关系都必须按照定义本身就是静态本身,这对于隔离也确实很不利,并且会阻止您用自己的代码替换(部分)创建逻辑。 Factory objects (or factory services) are slightly better. 工厂对象(或工厂服务)要好一些。 However, the need for them very likely points to some kind of design problem. 但是,对它们的需求很可能指向某种设计问题。 A service should not need a factory, since it will be created only once in a predetermined (and deterministic) way and from then on be perfectly reusable by any other object. 服务不需要工厂,因为它将仅以预定(确定性)的方式创建一次,并且此后可以被其他任何对象完美地重用。 The only things that are dynamic about a service, should be the arguments of the methods that are part of its public interface 关于服务的唯一动态内容应该是属于其公共接口的方法的参数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM