依赖注入:DIY容器或框架?

时间:2017-10-10 18:14:38

标签: php design-patterns dependency-injection auraphp

过去几天我一直在阅读关于依赖注入的大量内容,并且一直在使用Aura.DI来发挥IoC原则的作用。我在实施这种模式时遇到了一些我常常听到的问题,但我对某些细节还不太确定。

如果我想将一个记录器(比如Monolog)注入控制器类(只是一个简单的例子),我想使用类名作为记录通道(基本上是new Logger('somecontroller')),就我而言可以说,这意味着手动定义注射'对于每一堂课,我是否正确地思考这个?

此:

$controller = new PageController(new Logger('PageController'));
Aura.DI中的

将是:

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

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

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

我也遇到了this post on reddit并认为这有点道理。如果我不得不手动配置所有这些依赖项,为什么不让我的配置成为实际的实现呢?当依赖树变得更大时,这可能会崩溃吗?我认为有必要问一下什么样的民族'不过有意见。

编辑:只是mocked up an example DIY方法可以如何运作,实际上看起来很不错......想法? (可能应该将很多这些方法设为私有,但是你得到了图片)。

您可以对我的任何/所有问题提出任何意见。

1 个答案:

答案 0 :(得分: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. 使用相同Logger的{​​{3}}。可能这更容易了。您注入记录器并调用$newlogger = $this->logger->withName(__CLASS__);并获取克隆的新实例。

  3. 使用withName()

  4. 此处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还有自动分辨功能,有助于不编写大量配置。

    希望有所帮助!