zoukankan      html  css  js  c++  java
  • php设计模式-简单依赖注入容器+自动绑定特性

    class C
    {
        public function sayHello()
        {
            echo 'I am C';
        }
    }
    
    class B
    {
        private $_c;
    
        public function __construct(C $c)
        {
            $this->_c = $c;
        }
    
        public function sayHello()
        {
            echo 'I am B';
            $this->_c->sayHello();
        }
    }
    
    class A
    {
        private $_b;
    
        public function __construct(B $b)
        {
            $this->_b = $b;
        }
    
        public function sayHello()
        {
            echo 'I am A';
            $this->_b->sayHello();
        }
    }
    
    echo '<pre>';
    
    class Container
    {
        private $_map = array();
    
        public function __set($k, $c)
        {
            $this->_map[$k] = $c;
        }
    
        public function __get($k)
        {
            if (!isset($this->_map[$k])) throw new Exception('Undefined class');
            return $this->build($this->_map[$k]);
        }
    
        private function build($classname)
        {
            if ($classname instanceof Closure) return $classname($this);
    
            $reflection = new ReflectionClass($classname); // 涉及php反射相关知识
    
            // 检查类是否可实例化, 排除抽象类abstract和对象接口interface
            if (!$reflection->isInstantiable()) throw new Exception("接口不能被实例化");
    
            if ($reflection === null) throw new Exception('类未定义');
    
            $constructor = $reflection->getConstructor();
            
            if (is_null($constructor)) return new $classname;
            
            if (!$constructor->isPublic()) throw new Exception('类不能被实例化');
    
            $parameters = $constructor->getParameters();
    
            if ($parameters === null) return new $classname;
    
            // 递归解析构造参数
            $dependencies = $this->_getDependency($parameters);
    
            // 创建一个类的新实例,给出的参数将传递到类的构造函数。
            return $reflection->newInstanceArgs($dependencies);
        }
    
        private function _getDependency($parameters)
        {
            $dependencies = [];
    
            foreach ($parameters as $parameter) {
                $dependency = $parameter->getClass();
    
                if (is_null($dependency)) {
                    $dependencies[] = $this->_resolveClass($parameter);
                } else {
                    $dependencies[] = $this->build($dependency->name);
                }
            }
    
            return $dependencies;
        }
    
        private function _resolveClass($parameter)
        {
            if ($parameter->isDefaultValueAvailable()) {
                return $parameter->getDefaultValue();
            }
    
            throw  new  Exception('Unknow error');
        }
    }
    
    $di = new Container();
    $di->a = 'A';
    $di->a->sayHello();
    

      结果:

    I am AI am BI am C
    

      

  • 相关阅读:
    在Fedora 8 下安装Fcitx输入法
    iisweb服务器完美解决方案
    利用httpget实现计划任务访问某一指定页面
    如何升级到SQL Server 2005
    排除“计算机默认 权限设置未将 COM 服务器应用程序”的错误
    Windows 2003 服务器安全设置
    Linux Fedora8 下安装 IE6
    配置 SQL Server 以便使用 2 GB 以上的物理内存(包括SQL Server 2005)
    Entity Framework初探
    async、await在ASP.NET[ MVC]中之线程死锁的故事
  • 原文地址:https://www.cnblogs.com/xiangdongsheng/p/13363473.html
Copyright © 2011-2022 走看看