-
容器注入:也叫 依賴注入容器,
用戶在客戶端使用容器來進行類管理,還可以將類的實例(對象)做爲參數,傳遞給類方法,自動觸發依賴注入。
簡單的講就是將工具類打包成一個容器,在客戶端完成工具類的實例化爲對象,再以參數的方式直接傳遞給工作類的方法。
-
容器:也稱服務容器,簡稱(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();