Blogger Information
Blog 71
fans 1
comment 1
visits 86889
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
528-ThinkPHP5.1之容器注入(IOC)和门面模式(facade)
小威的博客
Original
2830 people have browsed it
  • 容器注入:也叫 依赖注入容器,

用户在客户端使用容器来进行类管理,还可以将类的实例(对象)做为参数,传递给类方法,自动触发依赖注入。

简单的讲就是将工具类打包成一个容器,在客户端完成工具类的实例化为对象,再以参数的方式直接传递给工作类的方法。

  • 容器:也称服务容器,简称(IOC)类似于:[即插即用]的工具,最大限度的简化外部对象的调用

  • 实现步骤有三步:

创建工具类

//数据库操作类
class Db
{
	//数据库连接
	public function connect()
	{
		return '数据库连接成功<br>';
	}
}

//数据验证类
class Validate
{
	//数据验证
	public function check()
	{
		return '数据验证成功<br>';
	}
}

//视图
class View
{
	//内容输出
	public function display()
	{
		return '用户登录成功';
	}
}

一、创建容器类:将类与类的实例化过程绑定到容器中(不局限于类,也可是接口或其它)

class Container
{
	//创建属性,用空数组初始化,该属性用来保存类与类的实例化方法
	protected $instance = [];

	//初始化实例数组,将需要实例化的类,与实例化的方法进行绑定
	public function bind($abstract, Closure $process)
	{
		//键名为类名,值为实例化的方法
		$this->instance[$abstract] = $process;
	}

	//创建类实例
	public function make($abstract, $params=[])
	{
		return call_user_func_array($this->instance[$abstract],[]);
	}
}

二、服务绑定:将可能用到的工具类全部绑定到容器中

      服务注册:将类实例注册到容器中

$container = new Container(); 

//将Db类绑定到容器中
$container->bind('db', function(){
	return new Db();
});

//将Validate类实例绑定到容器中
$container->bind('validate', function(){
	return new Validate();
});

//将View类实例绑定到容器中
$container->bind('view', function(){
	return new View();
});

三、容器依赖:将容器对象,以参数的方式注入到当前工作类中

      依赖容器:调用工作类时直接传入容器对象即可,工具类的实例化由容器完成

//用户类:工作类
class User
{
	//用户登录操作
	// public function login(Db $db, Validate $validate, View $view)
	//此时,只需从外部注入一个容器对象即可,Db,Validate和View实例方法全部封装到了容器中
	public function login(Container $container)
	{
		//实例化Db类并调用connect()连接数据库
		echo $container->make('db')->connect();

		//实例化Validate类并调用check()进行数据验证
		echo $container->make('validate')->check();

		//实例化视图类并调用display()显示运行结果
		echo $container->make('view')->display();
	}
}

客户端调用

//创建User类
$user = new User();

//调用User对象的login方法进行登录操作
//将该类依赖的外部对象以参数方式注入到当前方法中,推荐以构造器方式注入
echo '<h3>用依赖容器进行解藕:</h3>';
//工作类中的login方法不需要写三个对象了,只需要一个容器对象即可
echo $user->login($container);

下面案例使用依赖注入的思路是APP用到A类,A类需要B类,B类需要C类。那么先创建C类,再创建B类并把C注入,再创建A类,并把B类注入,再调用A方法,A调用B方法,接着做些其它工作。

<?php

class C
{
    public function doSomething()
    {
        echo __METHOD__, '我是C类|';
    }
}

class B
{
    private $c;

    public function __construct(C $c)
    {
        $this->c = $c;
    }

    public function doSomething()
    {
        $this->c->doSomething();
        echo __METHOD__, '我是B类|';
    }
}
class A
{
    private $b;

    public function __construct(B $b)
    {
        $this->b = $b;
    }

    public function doSomething()
    {
        $this->b->doSomething();
        echo __METHOD__, '我是A类|';;
    }
}

class Container
{
    private $s = array();

    function __set($k, $c)
    {
        $this->s[$k] = $c;
    }

    function __get($k)
    {
        return $this->s[$k]($this);
    }
}

$class = new Container();

$class->c = function () {
    return new C();
};
$class->b = function ($class) {
    return new B($class->c);
};
$class->a = function ($class) {
    return new A($class->b);
};


// 从容器中取得A
$foo = $class->a;
$foo->doSomething(); // C::doSomething我是C类|B::doSomething我是B类|A::doSomething我是A类|


  • 门面模式(facade) 也叫 外观模式   就是将操作进行封装,对外提供一个统一的接口

门面为容器中的类提供了一个静态调用接口,相比于传统的静态方法调用, 带来了更好的可测试性和扩展性,你可以为任何的非静态类库定义一个 facade 类。类似于一个导航网站,将多个网站,放在一个页面中,方便用户快速浏览各类网站。。

<?php 

//数据库操作类
class Db
{
	//数据库连接
	public function connect()
	{
		return '数据库连接成功<br>';
	}
}

//数据验证类
class Validate
{
	//数据验证
	public function check()
	{
		return '数据验证成功<br>';
	}
}

//视图
class View
{
	//内容输出
	public function display()
	{
		return '用户登录成功';
	}
}

//一、创建容器类
class Container
{
	//创建属性,用空数组初始化,该属性用来保存类与类的实例化方法
	public $instance = [];

	//初始化实例数组,将需要实例化的类,与实例化的方法进行绑定
	public function bind($abstract, Closure $process)
	{
		//键名为类名,值为实例化的方法
		$this->instance[$abstract] = $process;
	}

	//创建类实例
	public function make($abstract, $params=[])
	{
		return call_user_func_array($this->instance[$abstract],[]);
	}
}

//二、服务绑定: 将类实例注册到容器中
$container = new Container(); 

//将Db类绑定到容器中
$container->bind('db', function(){
	return new Db();
});

//将Validate类实例绑定到容器中
$container->bind('validate', function(){
	return new Validate();
});

//将View类实例绑定到容器中
$container->bind('view', function(){
	return new View();
});

//三、容器依赖:将容器对象,以参数的方式注入到当前工作类中
class Facade
{
	//创建成员属性保存容器对象
	protected static $container = null;

	//创建初始化方法为容器对象赋值
	public static function initialize(Container $container)
	{
		static::$container = $container;
	}
        
        //连接数据库
        public static function connect()
	{
		return static::$container->make('db')->connect();
	}

	//用户数据验证
	public static function check()
	{
		return static::$container->make('validate')->check();
	}

	//输出提示信息
	public static function display()
	{
		return static::$container->make('view')->display();
	}
}


//客户端调用

//初始化类门面类中的容器对象
Facade::initialize($container);

//静态统一调用内部的方法(无须重复注入依赖容器对象啦,实现了细节隐藏,通用性更强)
echo Facade::connect();
echo Facade::check();
echo Facade::display();

第三步可以单独调用

Correction status:Uncorrected

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post