根据马可的Pivetta思想,这个老问题以及我对另一个问题的回答
我一直在思考在Zend Framework 2中使用我们的服务的更好方法。
实际上,我们可以将ServiceLocatorAwareInterface
与ServiceLocatorAwareTrait
结合使用。事实上,在ZF3服务定位器将在控制器中删除。他们可能也会删除这个接口,或者建议人们不要使用它,这是有意义的。
我认为如何构建我们的服务的唯一方法是:
不要在服务中使用ServiceLocator,请使用DependencyInjection。
问题是:
有些项目太大了,你要么有:
- 一个工作流的15个服务类
- 有15名家属的服务级别
- 选择你的噩梦
您在服务中可能需要的一些示例:
- 取回formManager(不能在控制器中调用它)
- 在通过AJAX和JSON响应向视图返回HTML字符串之前,您可能需要让ViewRenderer渲染模板
- 您可能需要取回翻译器或ZF2提供的所有服务
- 获取您的实体经理,如果您有多个数据库,请在此处添加计数
- 获取其他服务,如MailService、ExportService、ImportService等
- 如果你必须加载特定的服务取决于客户端(BtoB中的多客户端网站…添加一些服务,因为你不能加载|调用AbstractFactory)
也许对于其中的一些点,它们可以通过我不知道的技巧来解决。
我的问题是:
一项服务有15名或15名以上家属是一种好的做法吗放弃ServiceLocator,在控制器中,但在服务中?
从评论中编辑
为了说明我的观点,我粘贴了我的一个构造函数:
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本身就是一个具有多个依赖关系的对象。此服务在我的应用程序文件夹中,几乎无处不在。我有两个实体经理(连接到两个数据库,但可能很快,我需要第三个…)
您可以看到,我通过依赖关系使用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);
}
假设您将注入ServiceLocator
实例。不能保证ServiceLocator
实际上包含了您的硬依赖项,从而打破了DI模式。当使用构造函数依赖项注入时,您可以确保所有需要的服务都是真正可用的。否则,服务的构建将失败。
当使用ServiceLocator
时,您将最终进入一个实例化的服务类,其中硬依赖项可能通过ServiceLocator
可用,也可能不可用。这意味着你必须编写所有类型的附加逻辑(检查依赖项,抛出异常),以防在你请求ServiceLocator
实例的那一刻无法解决依赖项。编写所有这些代码可能比注入15个依赖项要多得多,除此之外,整个服务的逻辑都会很混乱。
此外,您仍然需要添加所有的setter和getter方法,以便能够从ServiceLocator
获得服务,并使服务可测试。
IMHO注入15个依赖项比注入ServiceLocator
实例更少代码,更易于维护。