理解什么是Di/IoC,依赖注入/控制反转。两者说的是一个东西,是当下流行的一种设计模式。大致的意思就是,准备一个盒子(容器),事先将项目中可能用到的类扔进去,在项目中直接从容器中拿,也就是避免了直接在项目中到处new,造成大量耦合。取而代之的是在项目类里面增设 setDi()和getDi()方法,通过Di同一管理类。 当然,以上内容并不是重点,详细的概念推荐参考这篇文章: http://docs.phalconphp.com/en/latest/reference/di.html 中文版: http://phalcon.5iunix.net/reference/di.html

<?php
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);}
}

演示:

<?php
header("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');

转载于:https://www.cnblogs.com/hubing/p/5222596.html

PHP写的一个轻量级的DI容器类(转)相关推荐

  1. php写一个轻量级的容器,PHP写的一个轻量级的DI容器类

    直接上代码吧. Di容器类: class Di implements \ArrayAccess{ private $_bindings = array();//服务列表 private $_insta ...

  2. 为了去重复,写了一个通用的比较容器类,可以用在需要比较的地方,且支持Lamda表达式...

    为了去重复,写了一个通用的比较容器类,可以用在需要比较的地方,且支持Lamda表达式,代码如下: public class DataComparer<T>:IEqualityCompare ...

  3. 为了支持AOP的编程模式,我为.NET Core写了一个轻量级的Interception框架[开源]

    ASP.NET Core具有一个以ServiceCollection和ServiceProvider为核心的依赖注入框架,虽然这只是一个很轻量级的框架,但是在大部分情况下能够满足我们的需要.不过我觉得 ...

  4. 写的一个轻量级javascript框架的设计模式

    公司一直使用jQuery框架,一些小的项目还是觉得jQuery框架太过于强大了,于是自己周末有空琢磨着写个自己的框架.谈到js的设计模式,不得不说说js的类继承机制,javascript不同于PHP可 ...

  5. 自己写的一个轻量级javascript框架的设计模式

    2019独角兽企业重金招聘Python工程师标准>>> 公司一直使用 jQuery 框架,一些小的项目还是觉得jQuery框架太过于强大了,于是自己周末有空琢磨着写个自己的框架.谈到 ...

  6. 一个轻量级分布式RPC框架--NettyRpc

    1.背景 最近在搜索Netty和Zookeeper方面的文章时,看到了这篇文章<轻量级分布式 RPC 框架>,作者用Zookeeper.Netty和Spring写了一个轻量级的分布式RPC ...

  7. [UWP]实现一个轻量级的应用内消息通知控件

    [UWP]实现一个轻量级的应用内消息通知控件 原文:[UWP]实现一个轻量级的应用内消息通知控件 在UWP应用开发中,我们常常有向用户发送一些提示性消息的需求.这种时候我们一般会选择MessageDi ...

  8. **IOS:xib文件解析(xib和storyboard的比较,一个轻量级一个重量级)

    使用Xcode做iOS项目,经常会和Xib文件打交道,因为Xib文件直观的展现出运行时视图的外观,所以上手非常容易,使用也很方便,但对于从未用纯代码写过视图的童鞋,多数对Xib的理解有些片面. Xib ...

  9. 简单分享一个轻量级自动化测试框架目录结构设计

    更多关于python selenium的文章,请关注我的专栏:Python Selenium自动化测试详解 很多人在做自动化测试的过程中会遇到一个瓶颈,就是能够写脚本,但是不知道怎么去组织代码,怎么搭 ...

最新文章

  1. C++11:Lambda表达式(匿名函数)理解
  2. 倒序查10条数据_王者荣耀对抗路数据公布,尖端局吕布倒第一,夏洛特真的很意外...
  3. Linux 文件系统引起的云盘文件系统异常导致 MySQL 数据页损坏事故恢复复盘
  4. Ubuntu下用devstack单节点部署Openstack
  5. Python之tkinter:动态演示调用python库的tkinter带你进入GUI世界(Listbox/Scrollbar)
  6. 【网络安全】2022年第一次靶场渗透实战学习
  7. Xcode 新项目删除 storyboard 文件
  8. EJS学习(三)之语法规则中
  9. jinfo:JVM运行时配置的命令行浏览
  10. 【渝粤题库】陕西师范大学210015幼儿园社会教育作业(高起专)
  11. 收藏这些芯片原厂的代码仓库
  12. git两个账号切换_多个git账号之间的切换
  13. python牛顿法寻找极值_python使用梯度下降和牛顿法寻找Rosenbrock函数最小值实例...
  14. linux下安装phantomjs
  15. Python 标准库 —— 文件解压(zip、gz、pkl、tar)
  16. 【校招VIP】知名产品分析之微信本身的亮点和缺点
  17. MTK T750平台:CCCI驱动调试
  18. 4-9 Python对象的自省机制
  19. 2022.06青少年软件编程(Python)等级考试试卷(四级)
  20. html 表单自动填充,自动填充Web表单的方法与流程

热门文章

  1. Java 403 forbidden错误解决
  2. Android 制作类似支付圆圈和打钩界面ProgressWheel
  3. 夺命雷公狗---PHP开发APP接口---1(手动编写json)
  4. 推荐一个golang的json库
  5. WCF服务实现客户端Cookie共享,表单验证的解决方案
  6. Ajax框架,DWR介绍,应用,样例
  7. MikroTik RouterOS获取在线终端和在线IP总数并自动对IP做限速(转)
  8. 中国的EMM市场迎来爆发期?
  9. 树(1)------实现和遍历
  10. ASP.NET web.config