使用服务工厂在服务配置是在一些特殊情况下,更好的决策:
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 ):
我反对静态工厂方法的工厂类是 静态代码是全局代码,并且该执行该代码可能有侧面 无法隔离的影响(例如在测试场景中)。 此外,这种静态工厂方法的任何依赖性必须由定义为静态的本身,这对隔离也是非常不利的,并且 可以防止您用自己的 代码替换(部分)创建逻辑。工厂对象(或工厂服务)略好。 然而,需要对他们非常有可能指向某种设计 问题。服务不应该需要工厂,因为它只会以预定的(确定的)方式创建 一次,并且从此 可以被任何其他对象完全重用。这是 动态有关服务的唯一的东西,应该是那个 是
其他几个人要求其公共接口的一部分的方法的参数,发布您的特定使用案例的详细信息。尤其要区分“编译时”配置和基于请求的“运行时”配置。 – Cerad