依赖倒置原则(depend ence inversion principle,简称DIP),简单来说就是将依赖关系倒置为依赖接口,具体就是,上层模块不应该依赖于下层模块,它们共同依赖于一个抽象(父类不能依赖子类,应该共同依赖于抽象类)。抽象不能依赖于具体,但是具体应该依赖于抽象,我们要注意下,咱们这里的接口并不是指狭义上的接口。
因为接口体现了对问题的抽象,同时又因为抽象一般是相对稳定的,或者说相对变化不是太频繁,而具体是很容易就会产生变化的,所以我们依赖抽象是实现代码扩展和运行期内绑定(多态)的基础,只要实现了该抽象的子类,就都可以被类的使用者所使用。
咱们再来看下这个扩展性的概念啊,这个扩展性啊,通常是指对已知行为的扩展,并且咱们知道,接口是相对稳定的,所以,我们无论是用多么先进的设计模式,也不可能做到不需要修改代码就达到以不变应万变的地步,所以嘞,这个依赖倒置原则,我认为是最难理解和实现的。
先来看一个代码段:
interface employee
{
public function working();
}
class teacher implements employee
{
public function working()
{
// TODO: Implement working() method.
echo "teacher";
}
}
class coder implements employee
{
public function working()
{
// TODO: Implement working() method.
echo "coder";
}
}
class w_1
{
public function work()
{
$teacher = new teacher();
$teacher->working();
}
}
class w_2
{
private $a;
public function set(employee $a)
{
$this->a = $a;
}
public function work()
{
$this->a->working();
}
}
$w_1 = new w_1();
$w_1->work();
$w_2 = new w_2();
$w_2->set(new teacher());
$w_2->work();
咱们来梳理下上述代码,首先上述代码的w_1类的work方法,它的实现是依赖于teacher,但是w_2呢,是依赖于抽象来实现的,这样一来,我们就可以把需要的对象通过参数传入,就可以获取了,上述代码呢,通过接口,实现了一定程度上的解耦,但仍然是有限的,我们不仅仅是使用接口,使用工厂模式也是可以简单来实现一定程度的解耦和依赖倒置的。
在w_2类中,teacher实例通过set方法传入,实现了工厂模式,这样的方式是属于硬编码的,为了实现代码的进一步扩展,我们会把这个依赖关系写在配置文件里,指明了w_2类需要一个teacher实例对象,并且专门有一个程序来检测配置是否正确(如所以来的类文件是否存在等)以及加载配置中所依赖的实现,这个检测程序,我们可以称为IOC容器(inversion of control)。
IOC是依赖倒置原则的同义词,偶尔还会关联到DI、DS等概念,DI就是指依赖注入,DS就是指依赖查找,一般认为这两个东西是IOC的两种实现,不过,随着某些概念的演化,这几个概念之间的关系也变得很模糊,也有人认为IOC就是依赖注入,因为他们认为依赖注入的描述比IOC更加的贴切,咱们在这里就不讨论这个了啊。
事实上,很多设计模式里已经隐含了依赖倒置原则,我们也在有意无意的进行着一些依赖倒置的工作,这个依赖倒置它的核心是解耦,脱离了这个,一切都是本末倒置,并且在PHP里,目前来说还没有一个较为完善的IOC容器,并且如果是通过PHP来实现IOC容器等功能的话,倒不是不可以,只是从技术实现和运行效率方面来看的话,都是不符合我们使用PHP来进行开发的初衷的,咱们在这里呢,不对这个原则的好坏进行判断,只是简单介绍下这个原则。
满足依赖倒置原则有两个方面:
- 每个较高层次的类都为它所需要的服务提出一个接口声明,较低层次的类实现这个接口
- 每个高层类都通过该抽象接口使用服务
好啦,本次记录就到这里了。
如果感觉不错的话,请多多点赞支持哦。。。