天天看點

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) 也叫 外觀模式   就是将操作進行封裝,對外提供一個統一的接口