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

PHP工厂模式、依赖注入和控制反转

时间:2023-03-30 00:53:03 PHP

假设有一个商人在开水果摊。我们用下面的类来表示水果摊:classFruitStand{}水果摊会卖很多不同的水果,因为每一种水果都有独特的属性,所以每一种水果也可以用一个单独的类来表示。例如:AppleclassApple{protected$weight;//重量保护$sweet;//甜度publicfunction__construct($weight,$sweet){$this->weight=$weight;$this->sweet=$sweet;}}另一个例子:柠檬类Lemon{protected$weight;//重量保护$acid;//酸度publicfunction__construct($weight,$acid){$this->weight=$weight;$this->酸=$酸;}}现在,一个水果摊开张了。FruitStand类{protected$Fruits=[];//storefruitpublicfunction__construct(){//水果摊有这些水果$this->Fruits=array(newApple(2,100),newLemon(3,10));}}这时候可以发现依赖生成了。什么是依赖:“如果我依赖你,没有你就没有我”。从代码中可以看出,如果修改类Apple和类Lemon,类FruitStand将无法正常运行。如果想让类FruitStand正常运行,需要修改类FruitStand。而当增加一个新的水果时,类FruitStand的修改也是不可避免的。这意味着,如果给苹果加了一个属性,比如产地,那么水果摊也得整改。FruitStand类{protected$Fruits=[];//存储水果publicfunction__construct(){//水果摊有这些水果$this->Fruits=array(//newApple(2,100),苹果不见了,需要修改这个ClassnewLemon(3,10,111),//改变柠檬的属性,需要改变这个类newPear(),//添加新的梨,需要修改这个类//...//更多变化);}}通过上面的代码我们可以知道,每次商人想要改变某种水果的属性,都需要重新修改水果摊。显然,这是不对的。我们不应该把水果摊里面的水果搞定,而应该让外面负责。这时候,工厂模式应运而生,把水果摊水果种类的问题交给工厂去创造。就像,我们不需要自己创造每一个新的水果,而是交给工厂来帮助我们创造我们需要依赖的水果。我们只需要告诉工厂我们依赖哪些水果。这种对外负责其依赖需求的行为可以称为控制反转(IoC)水果摊加工厂:/***水果摊创建工厂*/classFruitStandFactory{//工厂创建水果摊的方法publicfunctionmake($fruits,$options){switch($fruits){case'Apple':returnnewApple($options[0],$options[1]);//创建苹果案例'Lemon':returnnewLemon($options[0],$options[1]);//创建柠檬案例'Pear':returnnewPear($options[0],$options[1],$options[2]);//createpear}}}使用水果架创建工厂,我们创建一个这样的水果架:/***fruitstandclass*/classFruitStand{protected$fruits=[];//存储水果publicfunction__construct(array$fruits)//参数$fruits意思是告诉工厂水果摊需要哪些水果{//向工厂求助$factory=newFruitStandFactory;//通过工厂提供的方法创建需要的水果摊foreach($fruitsas$name=>$options){$this->fruits[]=$factory->make($name,$options);}}}//创建一个水果摊$fruitStand=newFruitStand(['Apple'=>[1,2],'Lemon'=>[3,4]]);如果我们需要改变某个水果类的属性,只需要在FruitStandFactory水果摊类中修改或添加新的水果即可。也就是说,我们不需要自己去改装水果架,而是交给工厂去改装生产。然而,这仅仅是开始。最初,FruitStand依赖多个水果类(Apple、Lemon),但现在FruitStand依赖一个FruitStandFactory水果摊工厂类。当水果的种类增加时,水果工厂还是需要改造的。/***水果摊-创建工厂*/classFruitStandFactory{//工厂创建水果摊的方式publicfunctionmake($fruits,$options){switch($fruits){case'Apple':returnnewApple($选项[0],$选项[1]);//创建苹果案例'Lemon':returnnewLemon($options[0],$options[1]);//创建柠檬案例'Pear':returnnewPear($options[0],$options[1],$options[2]);//创建pear//case'xxx'//case'xxxx'//case'xxxxx'//...}}}这个时候到了,依赖注入。只要不是内部产生的(比如初始化,通过构造函数中的工厂方法__construct,或者自己手动new),而是从外部通过参数或者其他形式注入的,都属于依赖注入(DI)。FruitStand类{protected$fruit=[];publicfunction__construct(array$fruits){foreach($fruitsas$fruit){$this->fruit[]=$fruit;}}}//创建水果摊$Apple=newApple(1,2);$Lemon=newLemon(3,4);$fruitStand=newFruitStand([$Apple,$Lemon]);这时候如果我们添加一个新的水果,只需要添加新的依赖,将水果作为参数传入即可,不需要修改任何类。//创建一个水果摊$Apple=newApple(1,2);$柠檬=新柠檬(3,4);$Pear=newPear(5);//添加梨$fruitStand=newFruitStand([$Apple,$Lemon,$Pear]);