ZF2不推荐使用:ServiceManagerAwareInterface

Exl*_*ord 6 php dependency-injection zend-framework2 zend-framework3

今天我更新了我的项目,我得到了这个警告:

不推荐使用:ServiceManagerAwareInterface已弃用,将在3.0版中与ServiceManagerAwareInitializer一起删除.请更新您的类X以删除实现,并开始通过工厂注入您的依赖项

我有一些Base实现ServiceManagerAwareInterface扩展这些基类的多个类的主类.

那么为每个类创建额外的工厂类是一个好习惯吗?或者最好为每个模块使用1个AbstractFactory并在那里启动类?

使用AbstractFactory影响性能的剂量?

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

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

现在我允许每个服务/控制器利用其自身的需求和负载护理服务时,它需要它们.

这样我就不必启动我不会使用的多个服务,而且我不需要知道服务依赖项来使用它们.我知道这不是最佳实践,但代码很干净,我宁愿牺牲"最佳实践"来获得更好的表现.

感谢任何人对此的意见.

Ale*_*exP 5

通常,每项服务的工厂目标是一个理想的目标。但是,在许多情况下,当您具有相似的类且具有相似的依赖关系时,为每个工厂创建相同数量的工厂将是不必要且难以维护的。

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

这引入了一些问题。

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

  • 抽象工厂没有服务“别名”的概念。服务经理提供的功能。实现需要您对$requestedName服务进行匹配。如果您同时使用完整的服务名称和别名来调用服务,则会出现此问题。

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

该框架的路线图非常着重于解决这些问题,ZF3仍然提供抽象工厂,但是它也对工厂设计进行了一些改进,以鼓励您已经可以利用的可重用性

请注意,工厂现在接受其他必需的参数$requestedName;v2已经传递了此参数,但未在接口本身中指定。由于工厂现在可以期望收到服务名称,因此可以将它们重新用于多种服务,从而在很大程度上取代了版本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')
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以轻松地将其扩展为使用$requestedName参数加载定制服务配置,以增加更大的灵活性。

  • 您的更新确实是一个新问题。构造函数注入会将大量的对象图加载到内存中,这很浪费。您可以使用较少的依赖项来减少开销,从而使您的类更加具体,例如使用一种操作方法的控制器。然而,这意味着更多的工厂。另一种选择是[懒惰服务](http://framework.zend.com/manual/current/en/modules/zend.service-manager.lazy-services.html),它可以通过将返回的代理对象替换为昂贵的对象实例来提供帮助使用时的真实对象。 (2认同)