似乎有两种方法可以在Symfony中动态实例化服务:
这两种方法似乎都是最新的。检查问题和更改日志并没有给我任何关于最常见或哪种方法被认为是最佳实践的信息。
那么,我应该在工厂使用服务工厂而不是服务配置器或服务配置器吗?为什么,哪个是最近的?
非常感谢!
答案 0 :(得分:3)
基本上,它们不一样:工厂用于创建服务,配置器用于在创建服务后对其进行配置。
当您需要实例化服务(并注入其他服务或参数)时,请使用标准服务配置文件(即:services.yml
)。
当您需要控制服务实例时,请使用工厂。
如果需要在创建后配置服务,并且希望将服务定义与服务配置分开,请使用服务配置程序。
答案 1 :(得分:0)
在一些特殊情况下,使用服务工厂优于服务配置程序是更好的决定:
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):
我对使用静态工厂方法的工厂类的反对意见是 静态代码是全局代码,执行该代码可能有侧面 无法隔离的效果(例如在测试场景中)。 此外,必须遵循这种静态工厂方法的任何依赖性 定义静态本身,这对隔离也是如此 阻止您自己替换(部分)创建逻辑 码。工厂对象(或工厂服务)略胜一筹。 但是,对它们的需求很可能指向某种设计 问题。服务不应该需要工厂,因为它将被创建 只有一次以预定的(和确定的)方式从此开始 完全可以被任何其他物体重复使用。唯一的事情是 关于服务的动态,应该是方法的参数 是其公共界面的一部分