php---依赖倒转(反转控制)原则

一、简介

  依赖注入和控制反转说的实际上是同一个东西,它们是一种设计模式,这种设计模式用来减少程序间的耦合

  优点:使用依赖注入,最重要的一点好处就是有效的分离了对象和它所需要的外部资源,使得它们松散耦合,有利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活

  依赖倒置是一种软件设计思想,在传统软件中,上层代码依赖于下层代码,当下层代码有所改动时,上层代码也要相应进行改动,因此维护成本较高。而依赖倒置原则的思想是,上层不应该依赖下层,应依赖接口。意为上层代码定义接口,下层代码实现该接口,从而使得下层依赖于上层接口,降低耦合度,提高系统弹性

 

二、问题

  具有紧耦合关系的代码,往往迁一发而动全身。例如:

<?php
// dog 类
class dog {
    public function eat(){
        echo '骨头';
    }
    public function speak(){
        echo '旺旺';
    }
}
//cat 类
class cat {
    public function eat(){
        echo '鱼';
    }
    public function speak(){
        echo '喵喵';
    }
}

// BeastTraining 类
class BeastTraining{
    private $animal;
    public function __construct($animal){
        if ($animal == 'dog'){
            $this->animal = new dog();
        } else {
            $this->animal = new cat();
        }
    }
    public function eat(){
        $this->animal->eat();
    }
    public function speak(){
        $this->animal->speak();
    }
}

$animal = new BeastTraining('dog');
$animal->eat();

    上面的 BeastTraining 类与 dog 类 和 cat 类存在着紧耦合的关系,一旦dog类和cat 需要修改了eat方法,那么 BeastTraining 类也就要做相应的调整。或者又添加一个与cat 类相似的类,那此时有该怎么办呢?

 

三、解决方案

  以上的问题在于高层的代码(BeastTraining)依赖于底层的代码(dog 类或cat类),不利于代码的复用。如何减少对底层代码的依赖?解决方案:

<?php
interface animal{                    # 定义好接口
    public function eat();
    public function speak();
}

// dog 类
class dog implements animal {             # 实现接口类的 所有方法
    public function eat(){
        echo '骨头';
    }
    public function speak(){
        echo '旺旺';
    }
}
//cat 类
class cat implements animal{              # 实现接口的所有方法
    public function eat(){
        echo '鱼';
    }
    public function speak(){
        echo '喵喵';
    }
}

// BeastTraining 类
class BeastTraining{
    private $animal;
    public function __construct(animal $animal){      # 传输实现接口的类
        $this->animal = $animal;
    }
    public function eat(){
        $this->animal->eat();
    }
    public function speak(){
        $this->animal->speak();
    }
}


$animal = new BeastTraining(new cat());
$animal->eat();

 或者

<?php
abstract class animal{
    protected $status = 0;
    public function get_status()
    {
        echo $this->status;
    }
    abstract public function eat();
    abstract public function speak();
}

// dog 类
class dog extends animal {
    public $status=1;
    public function eat(){
        echo '骨头';
    }
    public function speak(){
        echo '旺旺';
    }
}
//cat 类
class cat extends animal{
    public $status=1;
    public function eat(){
        echo '鱼';
    }
    public function speak(){
        echo '喵喵';
    }
}

// BeastTraining 类
class BeastTraining{
    private $animal;
    public function __construct(animal $animal){
        $this->animal = $animal;
    }
    public function eat(){
        $this->animal->eat();
    }
    public function speak(){
        $this->animal->speak();
    }
    public function get_status(){
        $this->animal->get_status();    
    }
}

$animal = new BeastTraining(new cat());
$animal->eat();
$animal->get_status();

 

  上面两个代码案例其实是一样的,都解决了高层代码(BeastTrainnig 类)对底层代码(dog ,cat类)的依赖。通过对接口的定义。使底层代码符合接口规范,而高层代码又无需了解底层代码的实现过程。实现了高层代码与底层代码的解耦。

 

四、图解

  

 

 

 

五、总结

  1、高层模块不应该依赖于底层模块,两个都应该依赖于抽象

  2、抽象不应该依赖于细节,细节应该依赖于抽象

 

 

不足之处,请多多指教。

posted @ 2018-03-26 16:03  xiaobaiskill  阅读(420)  评论(0编辑  收藏  举报