我编写了一个使用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的人,或者出于单元测试的目的,仍然可以传入依赖关系。
这是一个坏主意,如果是这样,为什么?
答案 0 :(得分:1)
我同意@Unex。可以选择DI,但不是在构造函数中使用hardconding,而是在我的库中提供一个工厂。 通过这种方式,您可以保持与DI相同的松散耦合,并保持Client类的单一责任。为什么Client类知道如何构造其他类?类构造函数是关于自我知识的,仅此而已。请记住,构建一个完整的依赖链可能很大而且很复杂,也许你甚至必须在bootstrap中读取配置文件,访问在其他php模块中定义的常量,调用实用程序函数等;你不想在构造函数中包含所有这些代码。
答案 1 :(得分:1)
这正是我在开源项目中所做的,我认为这是一个非常好的解决方案。
它为用户提供了一种方法,可以毫不费力地开始使用您的库,同时让他们可以覆盖任何内容。
我有时选择的另一个解决方案是拥有builder class或factory,例如this constructor有强制参数,但ContainerBuilder
隐藏了这种复杂性。
构建器的优点是它使配置部分脱离了类。如果配置部分开始增长(关注点分离),这将非常有用。