ThinkPHP5.1之容器注入(IOC)和門面模式(facade)

  • 容器注入:也叫 依賴注入容器,

用戶在客戶端使用容器來進行類管理,還可以將類的實例(對象)做爲參數,傳遞給類方法,自動觸發依賴注入。

簡單的講就是將工具類打包成一個容器,在客戶端完成工具類的實例化爲對象,再以參數的方式直接傳遞給工作類的方法。

  • 容器:也稱服務容器,簡稱(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();
發佈了465 篇原創文章 · 獲贊 26 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章