ZF2 弃用:ServiceManagerAwareInterface

ZF2 Deprecated: ServiceManagerAwareInterface

今天我更新了我的项目并收到了这个警告:

Deprecated: ServiceManagerAwareInterface is deprecated and will be removed in version 3.0, along with the ServiceManagerAwareInitializer. Please update your class X to remove the implementation, and start injecting your dependencies via factory instead

我有一些实现 ServiceManagerAwareInterface 的主要 Base classes 和扩展这些基础 classes 的多个 classes。

那么,为每个 classes 创建额外的工厂 class 是一个好习惯吗?还是对每个模块使用 1 AbstractFactory 并在其中启动 classes 更好?

使用 AbstractFactory 影响性能?

在许多 class 中注入单个(或 2 个)共享依赖项的最佳实践是什么?

更新: 即使我接受了@AlexP 的回答,但我对提供依赖项抛出构造函数有一些担忧。想象一下这个场景:我有一个带有几个动作的控制器,以免说 ActionA 需要 ServiceZ 而 ActionB 需要 ServiceY 和 ServiceX,而 ServiceX 也依赖于 ServiceM 和 ServiceN。现在每次我调用 ActionA 时,我的控制器都会启动所有这些服务,但 ActionA 只需要 1 项服务,而我的控制器加载了 5 项服务....这是一个好习惯吗?这是正确的方法吗?这不会有糟糕的性能吗,因为在每次请求时都会启动我们在该请求期间根本不会使用的服务?

现在我允许每个 service/controller 照顾自己的需求并在 需要它们时加载服务

这样我就不必启动多个我不会使用的服务,也不需要知道服务依赖项就可以使用它们。我知道这不被接受为最佳实践,但代码很干净,我宁愿牺牲 "Best Practice" 以获得更好的性能。

感谢任何人对此的意见。

每项服务一个工厂通常是一个理想的目标;然而,在很多情况下,当您有相似的 类 具有相似的依赖关系时,为每个工厂创建那么多的工厂是不必要的,而且难以维护。

抽象工厂通过匹配 每个 它可以按名称创建的服务然后 return 使用一些自定义配置的新实例来解决多工厂问题。

这引入了一些问题。

  • $serviceManager->get()$serviceManager->has()的调用将要求抽象工厂检查它是否可以使用其canCreateServiceWithName()方法创建服务;对于多个抽象工厂,这可能会增加相当大的性能开销。

  • 抽象工厂没有服务的概念'alias';服务管理器提供的功能。该实现要求您匹配服务的 $requestedName。如果您使用完整的服务名称和别名调用服务,就会出现问题。

  • 抽象工厂与 ZF2 框架紧密耦合。

该框架的路线图非常注重解决这些问题,ZF3 仍然提供抽象工厂,但它也 introduces some improvements in factory design to encourage reusability 您已经可以利用它了。

Note that the factory now accepts an additional required argument, $requestedName; v2 already passed this argument, but it was not specified in the interface itself. Because factories now can expect to receive the service name, they may be re-used for multiple services, largely replacing abstract factories in version 3.

所以我们已经可以使用标准工厂 多次 次类似的服务(在 ZF2 中)。

关于如何使用一个工厂创建类似服务的一个非常简单的示例。

'service_manager' => [
    'factories' => [
        'My\Service\Foo' => 'My\Factory\SharedFactory',
        'My\Service\Bar' => 'My\Factory\SharedFactory',
        'My\Service\Baz' => 'My\Factory\SharedFactory',
    ],
],

namespace My\Factory;

class SharedFactory
{
    public function __invoke($serviceLocator, $name, $requestedName)
    {
        if (! class_exists($requestedName)) {
            throw new ServiceNotCreatedException("$requestedName could not be found!");
        }

        return new $requestedName(
            $serviceLocator->get('SomeDependacy1'),
            $serviceLocator->get('SomeDependacy2')
        );
    }
}

您可以使用 $requestedName 参数轻松扩展它以加载自定义服务配置,以增加更大的灵活性。