分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 教程案例

php依赖注入

发布时间:2023-09-06 01:50责任编辑:彭小芳关键词:暂无标签
在软件工程领域,依赖注入(Dependency Injection)是用于实现控制反转(Inversion of Control)的最常见的方式之一。本文主要介绍依赖注入原理和常见的实现方式,重点在于介绍这种年轻的设计模式的适用场景及优势。


首先我们来一个实例,上代码

<?phpclass A{public function test(){echo 'this is A!<br>';$b = new B();$b->test();}}class B{public function test(){echo 'this is B!<br>';$c = new C();$c->test();}}class C{public function test(){echo 'this is C!<br>';}}$obj = new A();$obj->test();


结果是:

this is A!this is B!this is C!


从代码分析,A类依赖B类,B类依赖C类。这是我们最原始的实现思路.这种实现思路很明显会有问题

假如我们现在B类修改下,代码如下:

class B{public $name;public function __construct($name){$this->name = $name;}public function test(){echo 'this is B'.$this->name.'!<br>';$c = new C();$c->test();}}


此时再看我们原来A类test方法直接调用明显会有问题,于是此时我们需要将原来代码:

class A{public function test(){echo 'this is A!<br>';$b = new B();$b->test();}}

修改成:

class A{public function test(){echo 'this is A!<br>';$b = new B('(class B)');//构造的时候多加了一个参数$b->test();}}

如果此时C类构造方法也变动了呢,B的方法里面也同样受影响,很明显可用性非常低


为了解耦,此时我们用到第二种思路:构造器注入,直接上代码:

<?phpclass A{public $obj;public function __construct(B $b){$this->obj = $b;}public function test(){echo 'this is A!<br>';$this->obj->test();}}class B{public $obj;public function __construct(C $c){$this->obj = $c;}public function test(){echo 'this is B!<br>';$this->obj->test();}}class C{public function test(){echo 'this is C!<br>';}}$c = new C();$b = new B($c);$obj = new A($b);$obj->test();

这种方法可以解决第一种方法,如果依赖的类构造方法(比如B类)有所改动,A类不需要改动任何代码。但是久而久之,这种方法毛病也出来了,我们首先必须要先实例化C类,再实例化B类,最后再实例化A类。


了解到第二种方案需要优化,于是出现了基本成型的第三种方案,此时我们用到了container(容器)和instance(实例),直接上代码:

class Container{public static $_classes = [];public static $_definations = [];public function get($class){if(isset(self::$_classes[$class]))return self::$_classes[$class];//当前类所依赖的类$depends = [];$tc = new ReflectionClass($class);//得到构造方法$constructor = $tc->getConstructor();//得到构造方法的参数if($constructor !== NULL){foreach($constructor->getParameters() as $parameter){if($parameter->isDefaultValueAvailable()){$depends[] = $parameter->getDefaultValue();}else{$pc = $parameter->getClass();$instance = Instance::getInstance($pc == NULL ? NULL : $pc->getName());$depends[] = $instance;}}}foreach($depends as $k => $v){if($v instanceof Instance){if($v->id !== NULL){$depends[$k] = $this->get($v->id);}}}$tm_instance = $tc->newInstanceArgs($depends);self::$_classes[$class] = $tm_instance;return $tm_instance;}}class Instance{/** * @var 类唯一标示 */public $id;/** * 构造函数 * @param string $id 类唯一ID * @return void */public function __construct($id){$this->id = $id;}/** * 获取类的实例 * @param string $id 类唯一ID * @return Object Instance */public static function getInstance($id){return new self($id);}}class Base{/** * 魔术方法 * @param string $name * @param string $value * @return void */public function __set($name, $value){$this->{$name} = $value;}}class A extends Base{private $instanceB;public function __construct(B $instanceB){$this->instanceB = $instanceB;}public function test(){echo 'this is A!<br/>';$this->instanceB->test();}}class B  extends Base{private $instanceC;public function __construct(C $instanceC){$this->instanceC = $instanceC;}public function test(){echo 'this is B!<br/>';return $this->instanceC->test();}}class C  extends Base{public function test(){echo 'this is C!';}}$container = new Container();$obj_a = $container->get('A');$obj_a->test();

此方法有参考yii2中yii2\di\container实现,只是将它简化了,更容易看懂。重点看看container的get方法


php依赖注入

原文地址:http://blog.51cto.com/chinalx1/2106072

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved