当前位置: 首页 > 后端技术 > PHP

PHP控制反转(IOC)和依赖注入(DI)

时间:2023-03-29 20:25:05 PHP

先看一个例子:b=newB();$this->c=newC();$this->b->方法();$this->c->方法();//TODO}}classB{publicfunctionB(){//TODO}publicfunctionMethod(){//TODOecho'b';}}classC{publicfunctionC(){//TODO}publicfunctionMethod(){//TODOecho'c';}}$a=newA();$a->Method();?>上面的代码,我们很容易理解一句话:A类依赖B类和C类。也就是说,如果在以后的开发过程中,我们需要修改B类或者C类。一旦函数名字改变了,函数参数个数改变了,甚至整个类结构调整了,我们也需要对A类做相应的调整,A类的独立性就失去了。这在开发过程中非常不方便,也就是我们所说的“全身而退”。如果两个类分别由两个人编写,这个时候往往会产生冲突。如果真的需要改B类和C类,有没有办法不改或者尽量少改A类的代码?这里使用了控制反转。高级模块不应该依赖于低级模块,两者都应该依赖于抽象。控制反转(IOC)是一个思想,依赖注入(DI)是实现这个思想的方法。第一种方法调用:构造函数注入(不推荐这种方法,但总比不这样做好)classA{public$b;公共$c;公共函数A($b,$c){$this->b=$b;$this->c=$c;}publicfunctionMethod(){$this->b->Method();$this->c->方法();}}客户端类是这样写的:$a=newA(newB(),newC());$a->Method();A类的构造函数依赖B类和C类,通过构造函数的参数传入,至少实现了一点,即B类对象b和C类对象c的创建移到了外面A类,所以一旦B类和C类发生改变,A类不需要修改,只要在客户端类中改变即可。如果有一天,我们需要扩展B类,使其成为B类的两个子类classB{publicfunctionB(){//TODO}publicfunctionMethod(){//TODOecho'b';}}classB1extendsB{publicfunctionB1(){//TODO}publicfunctionMethod(){echo'b1';}}classB2extendsB{publicfunctionB2(){//TODO}publicfunctionMethod(){echo'b2';}}也很简单,客户端类是这样写的:$a=newA(newB2(),newC());$a->Method();所以A类不需要关心B类的子类,只要在客户端类关心就可以了。调用第二种方法:工厂模式注入(推荐);休息;}case'C':{返回新C();休息;}默认值:{返回空值;休息;}}}}我们的A类代码改为:2468101214161820classA{public$b;公共$c;publicfunctionA(){//TODO}publicfunctionMethod(){$f=newFactory();$this->b=$f->create('B');$this->c=$f->create('C');$this->b->方法();$this->c->方法();//TODO}}其实已经解耦了一小部分,至少如果类B和C类的构造函数发生变化,比如修改函数参数,我们只需要改变Factory类即可。抽象不应该依赖于细节,细节应该依赖于抽象。将B类和C类中的方法抽象出来,做一个接口interfaceIMethod{publicfunctionMethod();}这样A类中的b变量、b变量、c变量就不再是一个具体的变量了。是一个抽象类型的变量,直到执行的那一刻,才知道他们的Method是怎么实现的。B类实现IMethod{publicfunctionB(){//TODO}publicfunctionMethod(){//TODOecho'b';}}C类实现IMethod{publicfunctionC(){//TODO}publicfunctionMethod(){//TODOecho'c';}}总结:1.我们把A类中B类对象和C类对象的创建移到了A类之外2.本来A类依赖B类和C类,现在变成了A依赖Factory,而Factory取决于B和C。