是否可以使用依赖注入回退?

时间:2015-03-31 08:33:02

标签: php dependency-injection

我编写了一个使用DI的开源PHP库。

对于想要使用它的人来说,库有一个单独的入口点, Client 类,它有一个看起来像这样的构造函数(简化):

class Client {

    protected $depOne;
    protected $depTwo;

    public function __construct(DependencyOne $depOne, DependencyTwo, $depTwo)
    {
        $this->depOne = $depOne;
        $this->depTwo = $depTwo;
    }
}

DependencyOne和DependencyTwo也有自己的依赖项。这意味着任何想要使用我的库不使用DI 的人都需要做这样的事情:

$dependencyThree = new DependencyThree();
$dependencyFour = new DependencyFour();
$dependencyFive = new DependencyFive();
$dependencyOne = new DependencyOne($dependencyThree, $dependencyFour);
$dependencyTwo = new DependencyTwo($dependencyFive);
$client = new Client($dependencyOne, $dependencyTwo);
$someStuff = $client->doTheThing();

这个类选择依赖注入会不会很糟糕? e.g。

class Client {

    protected $depOne;
    protected $depTwo;

    public function __construct(DependencyOne $depOne = null, DependencyTwo, $depTwo = null)
    {

        if (!isset($depOne)) {
            $depThree = new DependencyThree();
            $depFour = new DependencyFour();
            $depOne = new DependencyOne($depThree, $depFour);
        }

        if (!isset($depTwo)) {
            $depFive = new DependencyFive();
            $depTwo = new DependencyTwo($depFive);
        }

        $this->depOne = $depOne;
        $this->depTwo = $depTwo;
    }
}

这意味着不使用DI的人可以这样做:

$client = new Client();
$someStuff = $client->doTheThing();

那些想要使用DI的人,或者出于单元测试的目的,仍然可以传入依赖关系。

这是一个坏主意,如果是这样,为什么?

2 个答案:

答案 0 :(得分:1)

我同意@Unex。可以选择DI,但不是在构造函数中使用hardconding,而是在我的库中提供一个工厂。 通过这种方式,您可以保持与DI相同的松散耦合,并保持Client类的单一责任。为什么Client类知道如何构造其他类?类构造函数是关于自我知识的,仅此而已。请记住,构建一个完整的依赖链可能很大而且很复杂,也许你甚至必须在bootstrap中读取配置文件,访问在其他php模块中定义的常量,调用实用程序函数等;你不想在构造函数中包含所有这些代码。

答案 1 :(得分:1)

这正是我在开源项目中所做的,我认为这是一个非常好的解决方案。

它为用户提供了一种方法,可以毫不费力地开始使用您的库,同时让他们可以覆盖任何内容。

我有时选择的另一个解决方案是拥有builder classfactory,例如this constructor有强制参数,但ContainerBuilder隐藏了这种复杂性。

构建器的优点是它使配置部分脱离了类。如果配置部分开始增长(关注点分离),这将非常有用。