使此类符合依赖性倒置原则

时间:2012-11-07 18:18:45

标签: php oop zend-framework dependency-injection

维基百科引用的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不扩展抽象类或实现接口?

2 个答案:

答案 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有关。

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