zoukankan      html  css  js  c++  java
  • laravel学习:php写一个简单的ioc服务管理容器

    php写一个简单的ioc服务管理容器

    最近学习laravel框架,了解到laravel核心是一个大容器,这个容器负责几乎所有服务组件的实例化以及实例的生命周期管理。这种方式能够很好地对代码进行解耦,使得应用程序的业务代码不必操心服务组件的对象从何而来,当需要一个服务类来完成某个功能的时候,仅需要通过容器解析出该类型的一个实例即可。

    最近很焦虑,感觉自己的竞争力越来越弱(现阶段已完全成为一个IT搬砖工),道理大家都懂,但是想要摆脱搬砖工,走向砌墙工需要技术的慢慢积累,千里之行始于足下,那么这个周末就先写一个简单的ioc容器吧 哈哈。。。。

    参考了laravel容器的源码,简单分析一番,ioc容器只需实现两个功能,

    一、 注册服务(bind) 

             一般都是在程序刚加载的时候进行服务的注册,只是注册,不进行实例化,在真正用到的时候再进行实例化,这样做减少了资源浪费,做到了按需分配资源。

            有些特殊类是单例模式,再注册的时候进行区分

    二、实例化服务(make)

            从已注册服务的列表中选取要实例化的服务,返回实例对象

    =====================================

    Container.class.php 代码如下

    =====================================

    <?php

    class Container implements ArrayAccess

    {

    //注册服务列表

    private $_bindings = array();

    //实例服务列表

    private $_instances = array();

    //注册普通服务

    public function set($name,$class)

    {

    $this->bind($name,$class);

    }

    //注册单例服务

    public function setShared($name,$class)

    {

    $this->bind($name,$class,true);

    }

    //注册服务

    private function bind($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);

    }

    }

    //获取服务

    public function make($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);

    $obj = $concrete;

    }

    }

    //如果是单例模式,则写入_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]);

    }

    //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);  

    }

    }

    ?>

    =========================================

    index.php 测试代码

    先声明一个汽车接口类Car,接口有个paiLiang方法

    不同品牌的汽车实现Car接口 (假设一个品牌汽车就一种排量)

    实现了通过IOC容器管理类的注册和实例化以及依赖注入(通过注入不同的Car实现类,制造不同排量的汽车)

    =========================================

    <?php

    header("Content-Type:text/html;charset=utf8");

    include("Container.class.php");

    interface Car

    {

    //排量

    public function paiLiang();

    }

    class Audi implements Car

    {

    public function paiLiang()

    {

    return "我是奥迪,排量3.0L";

    }

    }

    class Bmw implements Car

    {

    public function paiLiang()

    {

    return "我是宝马,排量2.0T";

    }

    }

    class CarFactory

    {

    public $paiLiang;

    public function __construct(Car $car)

    {

    $this->paiLiang = $car->paiLiang();

    }

    }

    //实例化容器

    $app = new Container();

    //注册奥迪和宝马服务

    $app->set('audi','Audi');

    $app->set('bmw','Bmw');

    //注册汽车生产服务

    $app->set('carFactory','CarFactory');

    //echo $audi->paiLiang();

    //获取要生产奥迪车的排量

    $newCar = $app->make('carFactory',array($app->make('audi')));

    print_r($newCar->paiLiang.'<br>');

    $newCar = $app->make('carFactory',array($app->make('bmw')));

    print_r($newCar->paiLiang);

    输出结果:

    我是奥迪,排量3.0L
    我是宝马,排量2.0T

  • 相关阅读:
    NEC学习 ---- 模块 -多行式面包屑导航
    NEC学习 ---- 模块 -文本圆角背景导航
    NEC学习 ---- 布局 -三列,右侧自适应
    NEC学习 ---- 布局 -三列,左侧自适应
    NEC学习 ---- 布局 -三列, 左右定宽,中间自适应
    NEC学习 ---- 布局 -两列定宽
    NEC学习 ---- 布局 -两列, 右侧定宽,左侧自适应
    jquery weibo 留言
    原生js+本地储存登录注册
    原生捕鱼
  • 原文地址:https://www.cnblogs.com/guiyishanren/p/10578919.html
Copyright © 2011-2022 走看看