克隆依赖项的副本(依赖注入)是否有意义?

时间:2013-07-25 01:58:30

标签: php oop dependency-injection

假设我有一个类有一些依赖于另一个对象的方法来执行它们的职责。不同之处在于它们都依赖于同一类对象,但需要不同的类实例。或者更具体地说,每个方法都需要一个干净的类实例,因为这些方法将修改依赖项的状态。

这是我想到的一个简单例子。

class Dependency {
    public $Property;
}


class Something {
    public function doSomething() {
        // Do stuff
        $dep = new Dependency();
        $dep->Property = 'blah';
    }

    public function doSomethingElse() {
       // Do different stuff
       $dep = new Dependency(); 
       $dep->Property = 'blah blah';
    }
}

从技术上讲,我可以做到这一点。

class Something {
    public function doSomething(Dependency $dep = null) {
        $dep = $dep && is_null($dep->Property) ? $dep : new Dependency();
        $dep->Property = 'blah';
    }

    public function doSomethingElse(Dependency $dep = null) {
       $dep = $dep && is_null($dep->Property) ? $dep : new Dependency();
       $dep->Property = 'blah blah';
    }
}

我遇到的麻烦是我经常要检查传入的依赖对象是否处于正确的状态。新创建的州。所以相反,我正在考虑做这样的事情。

class Something {
    protected $DepObj;

    public function __construct(Dependency $dep) {
        $this->DepObj = $dep && is_null($dep->Property) ? $dep : new Dependency();
    }
    public function doSomething() {
        // Do stuff
        $dep = clone $this->DepObj;
        $dep->Property = 'blah';
    }

    public function doSomethingElse() {
       // Do different stuff
       $dep = clone $this->DepObj;
       $dep->Property = 'blah blah';
    }
}

这允许我以正确的状态获取对象的一个​​实例,如果我需要另一个,我可以复制它。我只是好奇这是否有意义,或者我是否正在寻找关于依赖注入和保持代码可测试的基本准则。

3 个答案:

答案 0 :(得分:4)

我会使用Factory模式:

class Dependency {
    public $Property;
}

class DependencyFactory
{
    public function create() { return new Dependency; }
}

class Something {
    protected $dependencies;

    public function __construct(DependencyFactory $factory) {
        $this->dependencies = $factory;
    }

    public function doSomething() {
       // Do different stuff
       $dep = $this->dependencies->create();
       $dep->Property = 'Blah';
    }

    public function doSomethingElse() {
       // Do different stuff
       $dep = $this->dependencies->create();
       $dep->Property = 'blah blah';
    }
}

您可以通过引入界面来进一步解耦工厂:

interface DependencyFactoryInterface
{
    public function create();
}

class DependencyFactory implements DependencyFactoryInterface
{
    // ...
}

class Something {
    public function __construct(DependencyFactoryInterface $factory) 
    ...

答案 1 :(得分:1)

DI是一种很棒的设计模式,但这并不意味着它适用于任何情况。在你的具体情况下,你说你每次都需要一个“新鲜”的副本,这意味着简单地使用“new”创建一个新实例比使用DI更有意义。

DI背后的想法是松散耦合 - 并允许代码中的不同位置使用相同的对象(除了它实现的接口之外一无所知) - 但在您的情况下,您不需要重复使用对象,因此我不会在这里使用DI。

答案 2 :(得分:0)

如果doSomething()doSomethingElse()在两个函数中都做类似的事情,那么它是一个糟糕的选择。在这种情况下,它创建了一个馈线功能,并为此功能提供了两个不同的对象。

但如果两个不同的动作都需要克隆依赖对象,那么它就不错了。