首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >注入还是注入新的?

注入还是注入新的?
EN

Stack Overflow用户
提问于 2012-10-24 17:25:00
回答 5查看 684关注 0票数 17

关于在另一个类中使用类对象,最佳实践是什么?在class _construct语句中传递类对象还是创建新的类对象?

示例1:

代码语言:javascript
复制
class Foo {
    private $bar;

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

或示例2:

代码语言:javascript
复制
class Foo {

    private $bar;

    public function __construct(){
        $this->bar= NEW bar;
    }    
}

我意识到,显然理所当然的是,类文件必须已经包含在其他地方,并且在第一个实例中,这种类型的类对象需要已经存在,但我想知道每个方法的优点是什么,因为我需要编写许多使用数据库对象的类,并且我需要以最好的方式将其传递到类中。还有比这两个更好的第三种选择吗?

据我所知,第一种方法的优点是减少了几行代码,并且在使用DB的情况下,不需要创建新的连接。然而,第二个可能更好,因为它更自包含?不管怎么说,我想我应该请教专家。

EN

回答 5

Stack Overflow用户

发布于 2012-10-24 17:30:18

您应该选择选项1,因为这是最简单的依赖注入形式。

在选项1中:

  • 类是相互独立的,
  • 类可以独立测试,使用的是模拟bar类
票数 10
EN

Stack Overflow用户

发布于 2012-10-24 17:39:50

一般而言,出于How to Think About the “new” Operator with Respect to Unit Testing中概述的原因,我赞同DI人群的观点

但是依赖注入如此重要的原因是,在单元测试中,您希望测试应用程序的一小部分。其要求是,您可以独立于整个系统构建应用程序的较小子集。如果您将应用程序逻辑与图构造(新操作符)混合在一起,则除了应用程序中的叶节点之外,单元测试将变得不可能。

将代码分成创建者图和协作者图将有助于保持代码的可维护性和可测试性。更好的是,根据接口编写代码,并且很容易将具体实现与其他实现进行交换。这使得更改代码变得很简单,因为您不必费力地在代码中寻找硬编码的依赖项。

例如,假设您的Bar需要一个记录器,您可以这样做

代码语言:javascript
复制
class Foo
{
    private $logger;

    public function __construct(LogInterface $logger)
    {
        $this->logger = $logger;
    }
}

然后传入实现该LogInterface的任何具体实现,如数据库记录器或StdOutLogger,或者可能包含这两者的复合记录器。另一个例子是数据库对象。您可以在引导程序中创建它一次,然后将其传递给使用它的对象。

如果有疑问,请使用依赖项注入。

然而,你并不总是需要注入东西。这取决于对象(您的工具栏)是否为Injectable or a Newable。引用Misko Hevery的话:

可注入类可以在其构造函数中请求其他Injectable。…可注入类往往具有接口,因为我们可能不得不用对测试友好的实现来替换它们。然而,Injectable永远不能在其构造函数中要求不可注入(Newable)。这是因为DI框架不知道如何生成Newable。…一些新闻的例子是:电子邮件,MailMessage,用户,CreditCard,歌曲。如果你保持这种区别,你的代码将很容易测试和使用。如果你违反了这个规则,你的代码将很难被测试。

简而言之,当您有一些无法合理注入的东西时,因为它是基于用户提供的信息或运行时信息,您可以对其进行new。对于值对象和数据类型更是如此:

代码语言:javascript
复制
class Foo
{
    private $storage;

    public function __construct()
    {
        $this->storage = new SplObjectStorage;
    }
}

注入SplObjectStorage是没有意义的。它只是一种数据类型。

票数 8
EN

Stack Overflow用户

发布于 2012-10-24 17:48:12

其他人已经回答了你的问题--一定要使用第一种方法,它使用依赖注入。

我只是想加入另一个您可能不知道的流行替代方案:使用依赖注入容器

一个很好、很简单的例子是Pimple;它是由Symfony框架背后的Fabien Potencier开发的。

示例3:

代码语言:javascript
复制
# In a bootstrap file...
require_once '/path/to/Pimple.php';

$container = new Pimple();
$container['bar'] = function ($c) {
    return new Bar(/** If bar has dependencies, put them here **/);
};

$container['foo'] = function ($c) {
    return new Foo($c['bar']);
};

# You'd still inject the service using DI, because it's not good 
# practice for your objects to rely directly on the container

class Foo {
    private $bar;

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

# The difference would be how you call Foo...
$foo = $container['foo'];

# So now your code doesn't need to know about the dependencies, and it's easy 
# to change them at any time by making a single change in your configuration

Symfony2使用了一个更健壮的容器,即also available as a standalone compenent。但Pimple可能是您最好的选择,除非您正在开发大型应用程序。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13046342

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档