Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 这是构造函数注入的合理实现吗?_Php_Design Patterns_Oop_Dependency Injection - Fatal编程技术网

Php 这是构造函数注入的合理实现吗?

Php 这是构造函数注入的合理实现吗?,php,design-patterns,oop,dependency-injection,Php,Design Patterns,Oop,Dependency Injection,继之后,我决定改用构造函数注入。请考虑以下代码: <?php interface IAppServiceRegistry { public function getDb(); public function getLogger(); } interface IFooServiceRegistry extends IAppServiceRegistry { public function getFooBarBazMo

继之后,我决定改用构造函数注入。请考虑以下代码:

<?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();
        }
    }

虽然我通常不阅读php,但我认为我理解它的大部分内容。从技术上讲,它看起来不错,但你写

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

这往往会损害松耦合的概念,因为您现在使用的不是通用的服务定位器,而是专门的服务定位器

将这样的serivce注册表注入到每个类中都会违反(SRP),因为一旦一个类访问了注册表,就很容易请求比最初设想的还要多的依赖项,最终会导致一个错误

最好将所需的依赖项直接注入到需要它们的类中。因此,您的Foo类的构造函数应该采用db、logger和fooModel,而BarBaz类应该只采用db和logger参数

接下来的问题可能是:如果我需要很多不同的依赖项来执行工作,该怎么办?这需要一个真正丑陋的构造函数,它有很多参数,这与其他众所周知的OO实践背道而驰


是的,但是如果您需要很多依赖项,那么您可能违反了SRP,应该尝试将您的设计拆分为更细粒度的对象:)

虽然我通常不阅读php,但我认为我理解其中的大部分内容。从技术上讲,它看起来不错,但你写

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

这往往会损害松耦合的概念,因为您现在使用的不是通用的服务定位器,而是专门的服务定位器

将这样的serivce注册表注入到每个类中都会违反(SRP),因为一旦一个类访问了注册表,就很容易请求比最初设想的还要多的依赖项,最终会导致一个错误

最好将所需的依赖项直接注入到需要它们的类中。因此,您的Foo类的构造函数应该采用db、logger和fooModel,而BarBaz类应该只采用db和logger参数

接下来的问题可能是:如果我需要很多不同的依赖项来执行工作,该怎么办?这需要一个真正丑陋的构造函数,它有很多参数,这与其他众所周知的OO实践背道而驰


是的,但是如果您需要很多依赖项,那么您可能违反了SRP,应该尝试将您的设计拆分为更细粒度的对象:)

此实现与您之前向我们展示的服务定位器几乎相同

一个好问题是,在查看对象的类时,您是否了解完成其工作所需的关于对象的所有信息。对你来说,你还是不知道

如果Foo需要db、logger和model,您可以在构造函数中请求它们来明确这一点

关于这件事,这里有一个很好的解读:


此实现与您之前向我们展示的服务定位器几乎相同

一个好问题是,在查看对象的类时,您是否了解完成其工作所需的关于对象的所有信息。对你来说,你还是不知道

如果Foo需要db、logger和model,您可以在构造函数中请求它们来明确这一点

关于这件事,这里有一个很好的解读:


我最近一直在努力解决这类问题。服务定位器与依赖注入

我同意Mark的观点,即方法是根据需要将单个细粒度对象注入构造函数。正如Mark所强调的,唯一的缺点是,当您构建一个复杂的对象图时,不可避免地必须从某个地方开始。这意味着您的高级对象将有许多服务(对象)注入其中

解决这个问题的简单方法是用一些东西为你做艰苦的工作。谷歌的Guice就是一个很好的例子,在我看来,它是一种很好的处理事情的方式。遗憾的是,它是为Java编写的!有关于PHP的版本;在这一点上,我不确定他们中是否有人完全符合Guice的要求

我写了一篇更详细的文章;你可能会觉得有趣。它包括一个依赖注入框架的简单实现

底线是,如果您有一个类Foo,具有许多需求,那么您可以创建这样的类:

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

    /**
     * (other documentation here)
     * @inject
     */
    public function __construct(IDbService $db, ILoggerService $logger, $iModelService $model)
    {
       // do something
    }
}
当您想要一个新的Foo对象时,只需请求依赖注入框架为您创建一个

$foo = $serviceInjector->getInstance('Foo');
依赖项注入器将进行艰苦的工作,确保它注入依赖项。这包括依赖项的任何依赖项(如果有意义的话)。换言之,它将在树上递归地进行排序


稍后,当您发现需要一个IBarService对象时,您可以将其添加到Construtor中,而无需修改任何其他代码

我最近一直在努力解决这类问题。服务定位器与依赖注入

我同意Mark的观点,即方法是根据需要将单个细粒度对象注入构造函数。正如Mark所强调的,唯一的缺点是,当您构建一个复杂的对象图时,不可避免地必须从某个地方开始。这意味着您的高级对象将有许多服务(对象)注入其中

解决这个问题的简单方法是用一些东西为你做艰苦的工作。谷歌的Guice就是一个很好的例子,在我看来,它是一种很好的处理事情的方式。遗憾的是,它是为Java编写的!有关于PHP的版本;在这一点上,我不确定他们中是否有人完全符合Guice的要求

我写了一篇更详细的文章;你可能会觉得有趣。它包括一个依赖项的简单实现