1

在过去的几天里,我一直在阅读大量有关依赖注入的文章,并且一直在使用 Aura.DI 来玩 IoC 原则。在实现此模式时,我遇到了一些我听说很常见的问题,但我仍然不太确定其中的一些细节。

如果我想将记录器(比如 Monolog)注入控制器类(只是一个简单的示例),我想使用类名作为日志记录通道(基本上new Logger('somecontroller')),据我所知,这意味着手动定义每个班级的“注射”,我这样想对吗?

这个:

$controller = new PageController(new Logger('PageController'));

在 Aura.DI 中,将是:

$di->params['PageController'] = [
    'logger' => $di->lazyNew('Logger', ['name' => 'PageController'])
];

但是我必须为每个需要不同日志记录通道的控制器执行此操作?!我听说您可以在这里使用抽象工厂模式,但我不确定这将如何工作?(我了解工厂模式,但从来没有遇到过我认为它会帮助我的情况。虽然抽象工厂模式对我来说是新的)

我知道我可以编写一个简单的方法来迭代一个控制器数组并以一种不那么冗长的方式执行此操作,但这样做确实感觉有点不对。

我也在reddit上看到了这篇文章,并认为它有点道理。如果无论如何我都必须手动配置所有这些依赖项,为什么不让我的配置成为实际的实现呢?当依赖关系树变大一点时,这可能会分崩离析?我认为值得询问人们的意见。

编辑:只是模拟了一个DIY方法如何工作的例子,实际上看起来还不错......想法?(可能应该将很多这些方法设为私有,但你明白了)。

您可以对我的任何/所有问题提出任何意见,我们将不胜感激。

4

1 回答 1

0

您可以通过几种不同的方式做到这一点。

  1. 向. LoggerFactory_PageController

    class PageController
    {
    
        public function __construct(LoggerFactory $loggerFactory)
        {
            $this->loggerFactory = $loggerFactory;
        }
    
        public function someAction()
        {
            $this->loggerFactory->newInstance(__CLASS__);
        }
    }
    
    class LoggerFactory
    {
        public function newInstance($name)
        {
            return new Logger($name);
        }
    }
    
  2. 使用相同的withName()Logger。可能这是更容易的一个。您注入记录器并调用$newlogger = $this->logger->withName(__CLASS__);并获取克隆的新实例。

  3. 使用实例工厂

这里ExampleNeedsFactoryPageControllerExampleStructLogger

$di->params['PageController']['loggerFactory'] = $di->newFactory('Logger');

    class PageController
    {

        public function __construct(LoggerFactory $loggerFactory)
        {
            $this->loggerFactory = $loggerFactory;
        }

        public function someAction()
        {
            $logger = $this->getLogger();
        }

        public function getLogger()
        {
            $this->loggerFactory->__invoke(__CLASS__);
        }
    }

注意:在这种情况下,getLogger总是返回新的记录器。如果您需要相同的实例,请设置记录器。

public function getLogger()
{
    if (! $this->logger) {
        $this->logger = $this->loggerFactory->__invoke(__CLASS__);
    }

    return $this->logger;
}

您还可以将这些方法移动到一个AbstractController类中,这样您就不需要每次都编写需要注入控制器的内容。(@camel_case 在他的评论中确实提到了这一点)

Aura.Di 也有自动解析功能,这有助于不编写大量配置。

希望有帮助!

于 2017-10-11T01:15:54.210 回答