这是构建器注入的一个合理的实现吗? [英] Is this a sane implementation of constructor injection?

查看:111
本文介绍了这是构建器注入的一个合理的实现吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是从我的服务定位器问题,我决定使用代替注入构造函数。请考虑以下代码:

Following on from my question on service locators I have decided to use constructor injection instead. Please consider the following code:

<?php

    interface IAppServiceRegistry {
        public function getDb();
        public function getLogger();
    }

    interface IFooServiceRegistry extends IAppServiceRegistry {
        public function getFooBarBazModel();
    }

    class AppServiceRegistry
        implements IAppServiceRegistry, IFooServiceRegistry
    {
        private $logger;
        private $db;
        private $fooBarBazModel;

        public function getDb() {
            // return db (instantiate if first call)
        }

        public function getLogger() {
            // return logger (instantiate if first call)
        }

        public function getFooBarBazModel() {
            if (!isset($this->fooBarBazModel)) {
                $this->fooBarBazModel = new FooBarBazModel( $this->getDb() );
            }
            return $this->fooBarBazModel;
        }
    }

    // Example client classes:

    /**
     * Depends on db, logger and foomodel.
     */
    class Foo {
        private $db;
        private $logger;
        private $fooModel;

        public function __construct(IFooServiceRegistry $services) {
            $this->db = $services->getDb();
            $this->logger = $services->getLogger();
            $this->fooModel = $services->getFooModel();
        }
    }

    /**
     * Depends on only db and logger.
     */
    class BarBaz {
        private $db;
        private $logger;

        public function __construct(IAppServiceRegistry $services) {
            $this->db = $services->getDb();
            $this->logger = $services->getLogger();
        }
    }

然后我会向注册表添加新的服务工厂方法随着应用程序的发展,在逻辑上适当地创建了隔离接口。

Then I would add new service factory methods to the registry as the application evolved, creating segregated interfaces wherever logically appropriate.

这个方法是否合理?

推荐答案

虽然我通常不读php,我觉得我理解的很多。在技​​术上,它看起来不错,但是你写的是

Although I don't normally read php, I think I understand most of it. Technically, it looks fine, but then you write


随着应用程序的发展,我将向注册表添加新的服务工厂方法

I would add new service factory methods to the registry as the application evolved

这往往会损害松耦合的想法,因为您现在有一个专门的服务定位器,而不是通用服务定位器。

That tends to hurt the idea of loose coupling because instead of a general-purpose Service Locator you now have a specialized Service Locator.

将这样一个服务注册表注入到每个类中,针对单一责任原则(SRP)因为一旦一个类有权访问注册表,它比原来构想的要求要容易得多,所以你最终会得到一个 God Object

Injecting such a serivce registry into each class works against the Single Responsibility Principle (SRP) because once a class has access to the registry, it is too easy to request yet another dependency than originally conceived, and you will end up with a God Object.

最好将所需的依赖项直接注入到需要的类中他们。因此,您的Foo类的构造函数应该使用数据库,记录器和fooModel,而BarBaz类应该只能使用db和logger参数。

It would be better to inject the required dependencies directly into the classes that need them. Thus, your Foo class' constructor should take a db, a logger and a fooModel, while the BarBaz class should take only a db and a logger parameter.

下一个问题可能是:如果我需要很多不同的依赖来执行工作怎么办?这将需要一个真正难看的构造函数,具有很多参数,这与其他着名的OO实践相反。

The next question may then be: What if I need a lot of different dependencies to perform the work? That would require a truly ugly constructor with lots of parameters, and this goes against other well-known OO practices.

如果你需要很多依赖项,可能违反SRP,并且应该尝试将您的设计分解成更细粒度的对象:)

True, but if you need lots of dependencies, you are probably violating the SRP and should try to split your design into finer-grained objects :)

这篇关于这是构建器注入的一个合理的实现吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆