6

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

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

我有一些Base实现这些基类的主类ServiceManagerAwareInterface和多个类。

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

使用 AbstractFactory 影响性能的剂量?

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

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

现在我允许每个服务/控制器处理自己的需求并在需要加载服务。

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

感谢任何人对此的投入。

4

1 回答 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以增加更大的灵活性。

于 2016-03-20T10:13:13.770 回答