我已经编写了一个使用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();
将的依赖项注入仅设为该类的可选项会不会很糟糕?例如
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或用于单元测试的人,依赖关系仍然可以传递
这是个坏主意吗?如果是,为什么?
这正是我在开源项目中所做的,我认为这是一个非常好的解决方案。
它为用户提供了一种不用付出任何努力就可以开始使用库的方式,同时也让他们可以覆盖任何内容。
我有时选择的另一个解决方案是有一个构建器类或工厂,例如,这个构造函数有强制参数,但ContainerBuilder
隐藏了这种复杂性。
构建器的优点是它将配置部分从类中移除。如果配置部分开始增长(关注点分离),这将非常有用。
我同意@Unex的观点。让DI成为可选的并不是坏事,但我会在我的库中提供一个工厂,而不是在构造函数中进行硬编译。通过这种方式,您可以保持与DI相同的松散耦合,并使Client类具有单一的责任。为什么客户端类知道如何构造其他类?类构造函数是关于自我认识的,仅此而已。请记住,构建整个依赖链可能又大又复杂,甚至可能需要在引导程序中读取配置文件、访问其他php模块中定义的常量、调用实用程序函数等;您不希望在构造函数中包含所有这些代码。