维基百科引用的DI的定义指出:
一个。高级模块不应该依赖于低级模块。两者都应该取决于抽象。 B.抽象不应该依赖于细节。细节应取决于抽象。
我正在尝试将该原则应用于我的代码:
class Printer{
private $logger;
function __construct(Zend_Log $logger){
$this->logger=$logger;
}
function print(){
//Some code
$this->logger->log('Logger in action ;)');
}
}
既然为什么Printer
类依赖于Zend_Log
,它既不是抽象类也不是接口,那么我违反了依赖性倒置原则。
如何知道Zend_Log
不扩展抽象类或实现接口?
答案 0 :(得分:5)
最简单的方法是使用接口适配器,例如创建您的打印机应该在接口中使用的API,然后在适配器中为Zend_Log组件实现该接口。将具体的适配器传递给打印机。然后打印机将依赖于PrinterLog而不是具体的Zend_Log。
interface PrinterLog
{
public function log($whatever);
}
class ZendPrinterLogAdapter implements PrinterLog
{
private $logger;
public function __construct(Zend_Log $logger)
{
$this->logger = $logger
}
public function log($whatever)
{
// delegate call to $this->logger
}
}
class Printer
{
private $logger;
function __construct(PrinterLog $logger)
{
$this->logger = $logger;
}
}
$printer = new Printer(new ZendPrinterLogAdapter(new Zend_Log));
答案 1 :(得分:2)
以下是相同API的替代方案..所以这将是标准设置:
interface Printerish // couldn't think of a good ajective
{
public function print();
}
interface CanLogStuff // couldn't think of a good ajective
{
public function log( $text );
}
class Printer implements Printerish
{
public function print()
{
// do something
}
}
这将是可记录的打印机:
class LoggedPrinter implements Printerish
{
protected $logger;
protected $pritner;
public function __construct( Printerish $printer, CanLogStuff $logger )
{
$this->logger = $logger;
$this->printer = $printer;
}
protected function print()
{
$this->logger( 'I can print, I can print !!' );
$this->printer->print();
}
}
这来自以下用例:如果在现实世界中你想开始控制真实打印机的使用(实习生再次printing out the internet)。然后你不会制作不同的打印机。您将尝试添加一些外部控件。
在编程中,它与Open/closed principle有关。
请记住,这只是一个想法,在尝试使用生产代码之前,应该仔细研究一下。