依赖注入回退可以吗?

Is it okay to have a dependency injection fallback?

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

库为想要使用它的人提供了一个入口点,即 Client class,它有一个如下所示的构造函数(简化):

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();

的依赖注入只是这个 class 可选是不是很糟糕?例如

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,或者为了单元测试目的,依赖还是可以传入的。

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

我同意@Unex。使 DI 成为可选的并不坏,但我会在我的库中提供一个工厂,而不是在构造函数中硬配置。 通过这种方式,您可以保持与 DI 相同的松散耦合,并让 Client class 承担单一责任。为什么客户端 class 知道如何构造其他 classes? Class constructor 就是自知之明,仅此而已。请记住,构建一个完整的依赖链可能又大又复杂,也许您甚至必须阅读 bootstrap 中的配置文件、访问其他 php 模块中定义的常量、调用实用程序函数等;您不想将所有这些代码都放在构造函数中。

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

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

我有时选择的另一种解决方案是 builder class or factory, see for example this constructor has mandatory parameter, but the ContainerBuilder 隐藏这种复杂性。

builder 的优势在于它将配置部分从 class 中取出。如果配置部分开始增长(关注点分离),这将很有用。