Php 我应该在构造函数中实例化其他类吗?

Php 我应该在构造函数中实例化其他类吗?,php,object,Php,Object,最近,我看到我的一位同事在构造函数中实例化了他的类,所以我开始做同样的事情,如下所示: class FooBar{ private $model1; private $model2; public function __construct() { $this->model1=new Model1(); $this->model2=new Model2(); } } 现在我开始怀疑,在需要模型的地方实例化模型是否会更好 例如,函

最近,我看到我的一位同事在构造函数中实例化了他的类,所以我开始做同样的事情,如下所示:

class FooBar{
private $model1;
private $model2;
    public function __construct() {
        $this->model1=new Model1();
            $this->model2=new Model2();
    }
}
现在我开始怀疑,在需要模型的地方实例化模型是否会更好

例如,函数
foo()
需要模型1,函数
bar()
需要模型2,但现在两个模型都已加载


所以,问题是:这是实例化其他类的正确方法吗?或者我应该在函数中需要它们时实例化它们吗?

我希望将这些依赖项作为参数注入到构造函数中。

在需要它们时,您应该实际加载它们,否则就需要一大堆不需要的模型(它们可能有自己的构造函数,加载更多的模型!)每次您需要完成一个简单的操作时,都会弹出到内存中


不要创建新模型,除非你确定你会使用它们(例如,需要本地化的模型等等)

这不是精确的科学,你应该按照你的直觉组织代码

如果这种方法无法维护,或者您想对其进行单元测试,依赖注入可能会起到解救作用


但是,如果您正在编写简单的脚本,并且开发时间是一个重要因素,那么您现在所采用的方式就足够了。

好吧,一如既往,没有一个万能的答案

大多数时候,类
FooBar
聚合了
$model1
$model2
,因为它需要它们来实现其功能。在这个场景中,除非
FooBar
在这些变量中有对象,否则它不能做很多事情,所以在构造函数中创建它们是正确的做法

有时,不需要聚合对象来执行类
FooBar
的大部分功能,并且构建该对象是一项昂贵的操作。在这种情况下,仅使用如下代码按需构建它是有意义的:

class FooBar {
    private $model1;
    private $model2;

    public function Frob() {
        $model = $this->getModel1();
        $model->frob();
    }

    private function getModel1() {
        if ($this->model1 === null) {
            $this->model1 = new Model1;
        }

        return $this->model1;
    }
}

然而,这只是有时候。如果类
FooBar
的一半操作需要
$model1
,另一半操作需要
$model2
,这可能表明
FooBar
遇到了“让我们把所有东西都扔到一个类中”的情况,应该分为两个类。

这取决于上下文。如果多次调用这些方法,是否每次都要实例化一个新模型?如果你想,真的有必要吗?是的,如果你需要在其他类的运行中创建实例,那么就注入一个工厂来创建它们。应该提供依赖项,而不是实例化依赖项,以便您可以用模拟实例替换它们进行测试。如果一个类已实例化,那么所有这些实例化和测试是否都可以在单独的类中完成?像一个全局类实例化类?听起来有点反常,但这会使实例化更加可重用。@Janis:测试,不是。实例化,是的。您可以提供对
FooBar
构造函数的回调,该构造函数将在调用时返回适当的模型,也可以一直使用依赖项注入容器()。由于您的答案包含了对我有价值的更多信息,因此我选择此作为可接受的答案。