7

维基百科引用的 DI 定义指出:

A. 高级模块不应该依赖于低级模块。两者都应该依赖于抽象。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知道既不扩展抽象类也不实现接口的情况下,我该如何解决?

4

2 回答 2

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));
于 2012-11-07T18:30:48.710 回答
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();
    }

}

这来自以下用例:如果在现实世界中您想开始控制真实打印机的使用(实习生已经再次打印出互联网)。那么你就不会制作不同的打印机了。您将尝试添加一些外部控制。

在编程中,它有点与开放/封闭原则有关。

请记住,这只是一个想法,在尝试在生产代码中使用之前应该仔细研究一下。

于 2012-11-07T19:06:25.460 回答