zoukankan      html  css  js  c++  java
  • 依赖注入模式

    1. https://my.oschina.net/cxz001/blog/533166
    依赖注入(Dependency Injection)是控制反转(Inversion of Control)的一种实现方式。
    
    我们先来看看什么是控制反转。
      当调用者需要被调用者的协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例,但在这里,创建被调用者的工作不再由调用者来完成,
    而是将被调用者的创建移到调用者的外部,从而反转被调用者的创建,消除了调用者对被调用者创建的控制,因此称为控制反转。
      要实现控制反转,通常的解决方案是将创建被调用者实例的工作交由 IoC 容器来完成,然后在调用者中注入被调用者(通过构造器/方法注入实现),这样我们就实现了调用者与被调用者的解耦,该过程被称为依赖注入。
    依赖注入不是目的,它是一系列工具和手段,最终的目的是帮助我们开发出松散耦合(loose coupled)、可维护、可测试的代码和程序。这条原则的做法是大家熟知的面向接口,或者说是面向抽象编程。

    下面是一个简化版本的Ioc容器, 完整版的可以观看相应框架的实现

      1 <?php
      2 
      3 /**
      4  * Ioc容器,这个是简化版本的,有些特性还是没有包含的
      5  */
      6 class Di implements ArrayAccess{
      7     private $_bindings = [];        //服务列表
      8     private $_instances = [];       //已经实例化的服务
      9 
     10     //获取服务
     11     public function get($name, $params=[]){
     12         //先从已经实例化的列表中查找
     13         if(isset($this->_instances[$name])){
     14             return $this->_instances[$name];
     15         }
     16 
     17         //检测有没有注册该服务
     18         if(!isset($this->_bindings[$name])){
     19             return null;
     20         }
     21 
     22         $concrete = $this->_bindings[$name]['class'];//对象具体注册内容
     23 
     24         $obj = null;
     25         //匿名函数方式
     26         if($concrete instanceof Closure){
     27             $obj = call_user_func_array($concrete,$params);
     28         }
     29         //字符串方式
     30         elseif(is_string($concrete)){
     31             if(empty($params)){
     32                 $obj = new $concrete;
     33             }else{
     34                 //带参数的类实例化,使用反射
     35                 $class = new ReflectionClass($concrete);
     36                 $obj = $class->newInstanceArgs($params);
     37             }
     38         }
     39 
     40         //如果是共享服务,则写入_instances列表,下次直接取回
     41         if($this->_bindings[$name]['shared'] == true && $obj){
     42             $this->_instances[$name] = $obj;
     43         }
     44 
     45         return $obj;
     46     }
     47 
     48     //检测是否已经绑定
     49     public function has($name){
     50         return isset($this->_bindings[$name]) or isset($this->_instances[$name]);
     51     }
     52 
     53     //卸载服务
     54     public function remove($name){
     55         unset($this->_bindings[$name], $this->_instances[$name]);
     56     }
     57 
     58     //设置服务
     59     public function set($name,$class){
     60         $this->_registerService($name, $class);
     61     }
     62 
     63     //设置共享服务
     64     public function setShared($name,$class){
     65         $this->_registerService($name, $class, true);
     66     }
     67 
     68 
     69 
     70 
     71 
     72     //注册服务
     73     private function _registerService($name,$class,$shared=false){
     74         $this->remove($name);
     75 
     76         if(!($class instanceof Closure) && is_object($class)){
     77             $this->_instances[$name] = $class;
     78         }else{
     79             $this->_bindings[$name] = array("class"=>$class,"shared"=>$shared);
     80         }
     81     }
     82 
     83     //ArrayAccess接口,检测服务是否存在
     84     public function offsetExists($offset) {
     85         return $this->has($offset);
     86     }
     87 
     88     //ArrayAccess接口,以$di[$name]方式获取服务
     89     public function offsetGet($offset) {
     90         return $this->get($offset);
     91     }
     92 
     93     //ArrayAccess接口,以$di[$name]=$value方式注册服务,非共享
     94     public function offsetSet($offset, $value) {
     95         return $this->set($offset,$value);
     96     }
     97 
     98     //ArrayAccess接口,以unset($di[$name])方式卸载服务
     99     public function offsetUnset($offset) {
    100         return $this->remove($offset);
    101     }
    102 }
    103 
    104 
    105 
    106 
    107 
    108 header("Content-Type:text/html;charset=utf8");
    109 class A{
    110     public $name;
    111 
    112     public function __construct($name=""){
    113         $this->name = $name;
    114     }
    115 }
    116 
    117 $di = new Di();
    118 
    119 
    120 //匿名函数方式注册一个名为a1的服务
    121 $di->setShared('a1',function($name=""){
    122     return new A($name);
    123 });
    124 
    125 $a1 = $di->get('a1',array("小李"));
    126 echo $a1->name."<br/>";//小李
    127 
    128 $a1_1 = $di->get('a1',array("小王"));
    129 echo $a1->name."<br/>";//小李
    130 echo $a1_1->name."<br/>";//小李
    131 
    132 
    133 
    134 //直接以类名方式注册
    135 $di->set('a2','A');
    136 
    137 $a2 = $di->get('a2',array("小张"));
    138 echo $a2->name."<br/>";//小张
    139 $a2_1 = $di->get('a2',array("小徐"));
    140 echo $a2->name."<br/>";//小张
    141 echo $a2_1->name."<br/>";//小徐
    142 
    143 
    144 
    145 //直接传入实例化的对象
    146 $di->set('a3',new A("小唐"));
    147 
    148 $a3 = $di['a3'];//可以直接通过数组方式获取服务对象
    149 echo $a3->name."<br/>";//小唐
    150 
    151 
    152 
    153 
    154 
    155 
    156 
    157 //删除服务则可以通过
    158 unset($di['a1']);
    159 
    160 or
    161 
    162 $di->remove('a1');
    163 
    164 
    165 //判断是否包含一个服务可以通过
    166 isset($di['a1']);
    167 
    168 or
    169 
    170 $di->has('a1');
    View Code
  • 相关阅读:
    C# 读取计算机CPU,HDD信息
    实现多线程下载文件
    安装SharePoint Server的主机重命名
    SharePoint 2010: Change welcome page on PowerShell
    FW: Solving SharePoint Server -503. The service is unavailable, After installation
    XDocument 使用
    ListBox 控件单击事件
    设计Popup Window
    Listbox Binding ItemsSource
    ListBox item Sort
  • 原文地址:https://www.cnblogs.com/hangtt/p/6250838.html
Copyright © 2011-2022 走看看