问题描述
根据 Marco 的 Pivetta 想法和 this,这 老问题以及我对另一个问题
According to Marco's Pivetta thoughts with this, this old questionand my answer to an other question
我在问自己在 Zend Framework 2 应用程序中使用我们服务的更好方式.
I was interrogating myself about the better way to use our Services in Zend Framework 2 application.
实际上我们可以将 ServiceLocatorAwareInterface
与 ServiceLocatorAwareTrait
结合使用.事实 在 ZF3 中服务定位器将在控制器中删除 可能他们也会移除这个界面,或者建议大家不要使用它,这是有道理的.
Actually we can use the ServiceLocatorAwareInterface
combined with ServiceLocatorAwareTrait
.With the fact In ZF3 service locator will be removed in controller It may be possible that they will also remove this interface, or advice people not using it, it make sense.
我了解如何构建我们的服务的唯一方法是:
The only way I see how our Services may be constructed is :
不要在你的服务中使用 ServiceLocator,使用 DependancyInjection.
问题是:
有些项目太大了,您可以选择:
Some project are just so big that you have either :
- 一个工作流的 15 个服务类.
- 具有 15 个依赖项的服务类.
- 选择你的噩梦...
您在服务中可能需要的一些示例:
Some example for what you may need in a service :
- 取回 formManager(不能在控制器中调用)
- 在通过 AJAX 和 JSON 响应将 HTML 字符串返回到视图之前,您可能需要让 ViewRenderer 呈现模板;
- 您可能需要取回翻译器或 ZF2 提供的每项服务
- 获取您的实体管理器,如果您有多个数据库,请在此处添加计数
- 获取其他服务,如 MailService、ExportService、ImportService 等...
- 如果您必须加载依赖于客户端的特定服务(BtoB 中的多客户端网站...添加一些服务,因为您无法加载 | 调用 AbstractFactory)
也许对于其中一些点,它们可以通过我不知道的技巧来解决.
Maybe for some of those points, they're can be solved by a tricks that I don't know.
我的问题是:
一项服务有 15 个或更多依赖项是否是一种好习惯并放弃 ServiceLocator,在控制器和服务中?
Is it a good practise to have 15 or more Dependancies for one service and give up the ServiceLocator, in controllers, but also in services ?
从评论中编辑
为了说明我的观点,我粘贴了我的一个构造函数:
For illustrate my point, I paste one of my constructor :
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 本身就是一个具有多个依赖项的对象.此服务在我的应用程序文件夹中,几乎无处不在.我有 2 个实体管理器(连接到 2 个数据库,但也许很快,我将需要第三个...)
As you can see, ToolboxService is an object with multiple dependancies itself. This Service is in my Application folder, and almost everywhere.I have 2 entity Managers (connection to 2 databases, but maybe soon, i will need a third one...)
你可以看到我通过一个依赖使用了 serviceLocator,所以这个服务没有实现 ServiceLocatorAwareInterface
.如果我不使用它,我会为我的 AbstractFactory 调用而搞砸
You can see that I use the serviceLocator throught a dependancy, so this service doesn't implements ServiceLocatorAwareInterface
. If I'm not using it, i'm literraly screwed for my AbstractFactory call with
// 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 模式.使用构造函数依赖注入时,您可以确定所有需要的服务都确实可用.否则,服务的构建就会失败.
Let's say you would inject the ServiceLocator
instance. There is no guarantee that the ServiceLocator
actually holds your hard dependencies, thus breaking the DI pattern. When using constructor dependency injection you are sure that all the services that are needed are really available. If not, the constructing of the service will simply fail.
当使用 ServiceLocator
时,您最终会进入一个实例化的服务类,其中硬依赖项可能会或可能不会通过 ServiceLocator
获得.这意味着您必须编写所有类型的附加逻辑(检查依赖项、抛出异常),以防在您请求时无法从 ServiceLocator
实例解析依赖项.编写所有这些代码可能比注入 15 个依赖项要多得多,而且最重要的是,整个服务的逻辑都会变得混乱.
When using a ServiceLocator
you will end up in an instantiated service class where hard dependencies might or might not be available through the ServiceLocator
. This means you have to write all kind of additional logic (check dependencies, throw exceptions) in case the dependency cannot be resolved from the ServiceLocator
instance the moment you ask for it. Writing all this code will probably be much more work then injecting 15 dependencies and on top of that the logic will be cluttered all over your service.
此外,您仍然需要添加所有的 setter 和 getter 方法,以便能够从您的 ServiceLocator
获取您的服务并使您的服务可测试.
Additionally you would still need to add all the setter and getter methods to be able to get your services from your ServiceLocator
and to make your service testable.
恕我直言,注入 15 个依赖项比注入 ServiceLocator
实例代码更少且更易于维护.
IMHO injecting 15 dependencies is less code and easier to maintain then injecting a ServiceLocator
instance.
这篇关于ServiceLocator,让我们在ZF2上下文中思考它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!