[DI] -- php写一个轻量级的容器
来源:互联网 发布:算法精解:c语言描述pdf 编辑:程序博客网 时间:2024/05/29 04:53
原文地址: https://my.oschina.net/cxz001/blog/227482
参考地址:https://segmentfault.com/a/1190000002424023
参考地址:http://www.digpage.com/di.html
摘要: 理解什么是Di/IoC,依赖注入/控制反转。两者说的是一个东西,是当下流行的一种设计模式。大致的意思就是,准备一个盒子(容器),事先将项目中可能用到的类扔进去,在项目中直接从容器中拿,也就是避免了直接在项目中到处new,造成大量耦合。取而代之的是在项目类里面增设 setDi()和getDi()方法,通过Di同一管理类。 当然,以上内容并不是重点,详细的概念推荐参考这篇文章: http://docs.phalconphp.com/en/latest/reference/di.html 中文版: http://phalcon.5iunix.net/reference/di.html
直接上代码吧.
Di容器类:
class Di implements \ArrayAccess{ private $_bindings = array();//服务列表 private $_instances = array();//已经实例化的服务 //获取服务 public function get($name,$params=array()){ //先从已经实例化的列表中查找 if(isset($this->_instances[$name])){ return $this->_instances[$name]; } //检测有没有注册该服务 if(!isset($this->_bindings[$name])){ return null; } $concrete = $this->_bindings[$name]['class'];//对象具体注册内容 $obj = null; //匿名函数方式 if($concrete instanceof \Closure){ $obj = call_user_func_array($concrete,$params); }elseif(is_string($concrete)){//字符串方式 if(empty($params)){ $obj = new $concrete; }else{ //带参数的类实例化,使用反射 $class = new \ReflectionClass($concrete); $obj = $class->newInstanceArgs($params); } } //如果是共享服务,则写入_instances列表,下次直接取回 if($this->_bindings[$name]['shared'] == true && $obj){ $this->_instances[$name] = $obj; } return $obj; } //检测是否已经绑定 public function has($name){ return isset($this->_bindings[$name]) or isset($this->_instances[$name]); } //卸载服务 public function remove($name){ unset($this->_bindings[$name],$this->_instances[$name]); } //设置服务 public function set($name,$class){ $this->_registerService($name, $class); } //设置共享服务 public function setShared($name,$class){ $this->_registerService($name, $class, true); } //注册服务 private function _registerService($name,$class,$shared=false){ $this->remove($name); if(!($class instanceof \Closure) && is_object($class)){ $this->_instances[$name] = $class; }else{ $this->_bindings[$name] = array("class"=>$class,"shared"=>$shared); } } //ArrayAccess接口,检测服务是否存在 public function offsetExists($offset) { return $this->has($offset); } //ArrayAccess接口,以$di[$name]方式获取服务 public function offsetGet($offset) { return $this->get($offset); } //ArrayAccess接口,以$di[$name]=$value方式注册服务,非共享 public function offsetSet($offset, $value) { return $this->set($offset,$value); } //ArrayAccess接口,以unset($di[$name])方式卸载服务 public function offsetUnset($offset) { return $this->remove($offset); }}
演示:
<?phpheader("Content-Type:text/html;charset=utf8");class A{ public $name; public $age; public function __construct($name=""){ $this->name = $name; }}include "Di.class.php";$di = new Di();//匿名函数方式注册一个名为a1的服务$di->setShared('a1',function($name=""){ return new A($name);});//直接以类名方式注册$di->set('a2','A');//直接传入实例化的对象$di->set('a3',new A("小唐"));$a1 = $di->get('a1',array("小李"));echo $a1->name."<br/>";//小李$a1_1 = $di->get('a1',array("小王"));echo $a1->name."<br/>";//小李echo $a1_1->name."<br/>";//小李$a2 = $di->get('a2',array("小张"));echo $a2->name."<br/>";//小张$a2_1 = $di->get('a2',array("小徐"));echo $a2->name."<br/>";//小张echo $a2_1->name."<br/>";//小徐$a3 = $di['a3'];//可以直接通过数组方式获取服务对象echo $a3->name."<br/>";//小唐
通过set和setShared方式注册服务,支持 匿名函数,类名字符串,已经实例化的对象.
两者的区别是:set方式注册的,每次获取的时候都会重新实例化setShared方式的,则只实例化一次,也就是所谓的单例模式
当然,对于直接注册已经实例化的对象,如上代码中的a3服务,set和setShared效果是一样的。
通过$di->get()获取服务,可接受两个参数,第一个参数是服务名,比如a1,a2,a3是必须的,第二个参数是一个数组,第二个参数会被当作匿名函数中的参数或者类构造函数里的参数传进去,参考call_user_func_array()。
删除服务则可以通过
unset($di['a1']);
or
$di->remove('a1');
判断是否包含一个服务可以通过
isset($di['a1']);
or
$di->has('a1');
就这么多了。
0 0
- [DI] -- php写一个轻量级的容器
- Guice:轻量级IOC/DI 容器
- 解读超轻量级DI容器-Guice与Spring框架的区别
- 解读超轻量级DI容器-Guice与Spring框架的区别
- 动手写一个STM8的轻量级bootloader
- 关于DIP,IoC,DI,以及IoC容器的一个说明
- 一个PHP实现的轻量级简单爬虫
- 一个PHP实现的轻量级简单爬虫
- 轻量级容器的比较
- 轻量级容器的比较
- Arrow--轻量级的Android DI 库
- 超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享
- 超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享
- 自己动手写一个轻量级的Android网络请求框架
- 自己动手写一个轻量级的Android网络请求框架
- C语言写的一个容器list
- 一个轻量级的c编写的php接口平台框架
- 发布一个轻量级的PHP实现的WEBSOKCET引擎-EZ_WS
- python实现常见算法
- rabbitMQ的交换机类型
- caffe
- 项目android 6.0,7.0 版本适配问题
- thinkPHP3.2获取当前语言名称
- [DI] -- php写一个轻量级的容器
- Java 字符串操作封装
- 聪明贝塔(Smart Beta)
- 宠物美容师行业有哪些优势
- shouldShowRequestPermissionRationale用法
- 单选按钮与复选按钮的相互转换
- 动态规划 钢条切割
- hdu2642-二维树状数组 单点更新 区间查询
- Recover后升级失败,unknown volume for path