假设我有一个类有一些依赖于另一个对象的方法来执行它们的职责。不同之处在于它们都依赖于同一类对象,但需要不同的类实例。或者更具体地说,每个方法都需要一个干净的类实例,因为这些方法将修改依赖项的状态。
这是我想到的一个简单例子。
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';
}
}
这允许我以正确的状态获取对象的一个实例,如果我需要另一个,我可以复制它。我只是好奇这是否有意义,或者我是否正在寻找关于依赖注入和保持代码可测试的基本准则。
答案 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()
在两个函数中都做类似的事情,那么它是一个糟糕的选择。在这种情况下,它创建了一个馈线功能,并为此功能提供了两个不同的对象。
但如果两个不同的动作都需要克隆依赖对象,那么它就不错了。