Container Laravel source of learning

Ioc mode

IOC ( Inversion of Control ) mode, also known as dependency injection ( the Dependency Injection ) mode. Inversion of control is to dependencies between the components transferred from the inside to the outside application program, and refers to the dependency dependency injection assembly by injection or other forms of external parameters, two versions of essentially the same.
The following is a simple example of dependency injection:

<?php
interface Visit
{
    public function go();
}

class Leg implements Visit
{
    public function go()
    {
        echo "walk to Tibet";   
    }
}

class Traveller
{
    protected $trafficTool;
    
    public function __construct(Visit $trafficTool)
    {
        $this->trafficTool = $trafficTool;
    }
    
    public function visitTibet()
    {
        $this->trafficTool->go();
    }
}

//生成依赖的交通工具实例
$trafficTool = new Leg();
//依赖注入的方式解决依赖问题
$tra = new Traveller($trafficTool);
$tra->visitTibet();

Examples of the above-described dependency injection is a simple process, Traveler class constructor dependency Visit instance with an external interface, and in the instance of Traveler, we pass a $ trafficTool example, i.e., to solve the problem by dependency injection dependent manner.
It should be noted that: the need to limit dependency injection via the interface, and not freely open, which mention is another principle of design patterns ---- interfaces for programming, rather than programming.
Here we are dependent by injecting manually, through Ioc can automatically dependency injection container. Next, the design method Laravel framework simplified, Ioc container to achieve complete dependency injection, as follows:

<?php
class Container
{
    /*
     *用于存储提供实例的回调函数,真正的容器还会装实例等其他内容
     *从而实现单例等高级功能
     */
    protected $bindings = [];

    //绑定接口和生成相应实例的回调函数
    public function bind($abstract, $concrete = null, $shared = false)
    {
        if ( ! $concrete instanceof Closure){
            //如果提供的函数不是回调函数,则产生默认的回调函数
            $concrete = $this->getClosure($abstract, $concrete);
        }
        $this->bindings[$abstract] = compact('concrete', 'shared');
    }

    //默认生成实例的回调函数
    protected function getClosure($abstract, $concrete)
    {
        //生成实例的回调函数, $c一般为IOC容器对象,在调用回调生成实例时提供
        //即build函数中的$concrete($this)
        return function($c) use ($abstract, $cocrete)
        {
            $method = ( $abstract == $concrete ) ? 'build' : 'make';
            //调用的是容器的build或make方法生成实例
            return $c->$method($concrete);
        };
    }

    //生成实例对象,首先解决接口和要实例化类之间的依赖关系
    public function make($abstract)
    {
        $concrete = $this->getConcrete($abstract);
        if ($this->isBuildable($concrete, $abstract)){
            $object = $this->build($concrete);
        } else {
            $object = $this->make($concrete);
        }

        return $object;
    }

    protected function isBuildable($concrete, $abstract)
    {
        return $concrete === $abstract || $concrete instanceof Closure;
    }

    //获取绑定的回调函数
    protected function getConcrete($abstract)
    {
        if ( ! isset($this->bindings[$abstract])){
            return $abstract;
        }

        return $this->bindings[$abstract]['concrete'];
    }
    //实例化对象
    public function build($concrete)
    {
        if ($concrete instanceof Closure) {
            return $concrete($this);
        }
        $reflector = new ReflectionClass($concrete);
        if (! $reflector->isInstantiable()){
            echo $message = "Target [$concrete] is not instantiable";
        }
        $constructor = $reflector->getConstructor();
        if (is_null($constructor)){
            return new $concrete;
        }
        $dependencies = $constructor->getParameters();
        $instances = $this->getDependencies($dependencies);
        return $reflector->newInstanceArgs($instances);
    }
    //解决通过反射机制实例化对象时的依赖
    protected function getDependencies($parameters)
    {
        $dependencies = [];
        foreach ($parameters as $parameter) {
            $dependency = $parameter->getClass();
            if (is_null($denpendency)){
                $dependencies[] = NULL;
            } else {
                $dependencies[] = $this->resolveClass($parameter);
            }
        }
        return (array) $dependencies;
    }

    protected function resolveClass(ReflectionParameter $parameter)
    {
        return $this->make($parameter->getClass()->name);
    }
}

class Traveller
{
    protected $trafficTool;
    public function __construct(Visit $trafficTool)
    {
        $this->trafficTool = $trafficTool;
    }

    public function visitTibet()
    {
        $this->trafficTool->go();
    }
}
//实例化Ioc容器
$app = new Container();
//完成容器的添加
$app->bind("Visit", "Train");
$app->bind("traveller", "Traveller");
//通过容器实现依赖注入,完成类的实例化
$tra = $app->make("traveller");
$tra->visitTibet();

Through the above code, we can achieve Ioc container core functions, solve the fundamental problem of dependency injection. During implementation, be implemented without using new object instance, the dependencies between the components need not be concerned, only straighten out the relationship between the interface and the implementation class and classes implemented in the container during filling and dependence Interface the relationship between, can be pipelined to achieve complete implementation class. Examples of this class is accomplished by reflection.

Guess you like

Origin www.cnblogs.com/uneasy96/p/12149281.html