ZF2已弃用:ServiceManagerAwareInterface

6
今天我更新了我的项目,然后得到了这个警告:
Deprecated: ServiceManagerAwareInterface已被弃用,并将在3.0版本中删除,以及ServiceManagerAwareInitializer。请更新您的类X以删除实现,并开始通过工厂注入您的依赖项
我有一些主要的Base类,它们实现了ServiceManagerAwareInterface,并且有多个继承这些基类的类。
那么为每个这些类创建一个额外的工厂类是一个好的实践吗?还是使用1个AbstractFactory来初始化模块中的所有类更好?
使用AbstractFactory会影响性能吗?
注入单个(或2个)共享依赖项到多个类的最佳实践是什么?
更新: 尽管我接受了@AlexP的答案,但我对通过构造函数提供依赖项有一些担忧。想象一下这种情况:我有一个控制器和几个操作,例如ActionA需要ServiceZ,而ActionB需要ServiceY和ServiceX,而ServiceX还依赖于ServiceM和ServiceN。现在,每次调用ActionA时,我的控制器都会被初始化为这些服务,但ActionA只需要1个服务,其中我的控制器加载了5个服务...这是一个好的实践吗?这是正确的方法吗?由于在每个请求期间都会启动不会使用的服务,是否会影响性能?
现在,我允许每个服务/控制器自己处理其自身需求并在需要时加载服务。这样,我就不必初始化多个不会使用的服务,并且我不需要知道服务的依赖关系才能使用它们。我知道这不被认为是最佳实践,但代码很干净,我更愿意牺牲“最佳实践”以获得更好的性能。
感谢任何人对此的输入。
1个回答

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')
        );
    }
}

您可以轻松地通过使用$requestedName参数来加载自定义服务配置,以实现更大的灵活性。

谢谢您的回答,我不知道工厂提供服务名称,我更新了问题,请有时间的话看一下。 - Exlord
2
你的更新实际上是一个新问题。构造函数注入可以将大量对象图加载到内存中,这是浪费的。您可以通过减少依赖项来减少开销,使您的类更具体,例如只有一个操作方法的控制器。这意味着需要更多的工厂。另一个选择是延迟服务,它通过使用代理对象替换昂贵的对象实例化来帮助返回真正的对象。 - AlexP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接