Laravel 控制反轉和門面模式概念詳解

這兩個概念對於 Laravel 的使用者來講應該並不陌生,尤爲是當你但願擴展或者替換 Laravel 核心庫的時候,理解和合理使用它們能夠極大提高 Laravel 的戰鬥力。這裏以建立一個本身的 ServiceProvider 爲例理解 Inversion of Control 和 Facade 在 Laravel 中的應用。php

控制反轉(Inversion of Control)

什麼是 IoC

控制反轉(Inversion of Control,縮寫爲IoC),是面向對象編程中的一種設計原則,能夠用來減低計算機代碼之間的耦合度。其中最多見的方式叫作依賴注入(Dependency Injection,簡稱DI),還有一種方式叫「依賴查找」(Dependency Lookup)。經過控制反轉,對象在被建立的時候,由一個調控系統內全部對象的外界實體,將其所依賴的對象的引用傳遞給它。 — 維基百科html

簡單說來,就是一個類把本身的的控制權交給另一個對象,類間的依賴由這個對象去解決。依賴注入屬於依賴的顯示申明,而依賴查找則是經過查找來解決依賴。laravel

Laravel 中的使用

注入一個類:編程

App::bind('foo', function($app)
{
    return new FooBar;
});

這個例子的意思是建立一個別名爲 foo 的類,使用時實際實例化的是 FooBar。數組

使用這個類的方法是:app

$value = App::make('foo');

$value 其實是 FooBar 對象。ide

若是但願使用單例模式來實例化類,那麼使用:this

App::singleton('foo', function()
{
    return new FooBar;
});

這樣的話每次實例化後的都是同一個對象。spa

注入類的更多例子能夠看 Laravel 官網設計

你可能會疑問上面的代碼應該寫在哪兒呢?答案是你但願他們在哪兒運行就寫在哪兒。0 —— 0 知道寫哪兒還用來看這種基礎文章麼!

服務提供器 (Service Providers)

爲了讓依賴注入的代碼不至於寫亂,Laravel 搞了一個 服務提供器(Service Provider)的東西,它將這些依賴彙集在了一塊,統一申明和管理,讓依賴變得更加容易維護。

Laravel 中的使用

定義一個服務提供器:

use Illuminate\Support\ServiceProvider;

class FooServiceProvider extends ServiceProvider {

    public function register()
    {
        $this->app->bind('foo', function()
        {
            return new Foo;
        });
    }

}

這個代碼也不難理解,就是申明一個服務提供器,這個服務提供器有一個 register的方法。這個方法實現了咱們上面講到的依賴注入。

當咱們執行下面代碼:

App::register('FooServiceProvider');

咱們就完成一個注入了。可是這個仍是得手動寫,因此怎麼讓 Laravel 本身來作這事兒呢?

咱們只要在 app/config/app.php 中的 providers 數組裏面增長一行:

'providers' => [
    …
       ‘FooServiceProvider’,
],

這樣咱們就能夠使用 App::make(‘foo’) 來實例化一個類了。

你不由要問了,這麼寫也太難看了吧?莫慌,有辦法。

門面模式(Facade)

爲了讓 Laravel 中的核心類使用起來更加方便,Laravel實現了門面模式。

外觀模式(Facade pattern),是軟件工程中經常使用的一種軟件設計模式,它為子系統中的一組接口提供一個統一的高層接口,使得子系統更容易使用。 — 維基百科

Laravel 中的使用

咱們使用的大部分核心類都是基於門面模式實現的。例如:

$value = Cache::get('key');

這些靜態調用實際上調用的並非靜態方法,而是經過 PHP 的魔術方法__callStatic() 講請求轉到了相應的方法上。

那麼如何講咱們前面寫的服務提供器也這樣使用呢?方法很簡單,只要這麼寫:

use Illuminate\Support\Facades\Facade;

class Foo extends Facade {

    protected static function getFacadeAccessor() { return ‘foo’; }

}

這樣咱們就能夠經過 Foo::test() 來調用咱們以前真正的 FooBar 類的方法了。

別名(Alias)

有時候咱們可能將 Facade 放在咱們擴展庫中,它有比較深的命名空間,如:\Library\MyClass\Foo。這樣致使使用起來並不方便。Laravel 能夠用別名來替換掉這麼長的名字。

咱們只要在 app/config/app.php 中 aliases 下增長一行便可:

'aliases' => [
    …
    'Foo' => ‘Library\MyClass\Foo’,
],

這樣它的使用就由 \Library\MyClass\Foo::test() 變成 Foo::test() 了。

總結

因此有了控制反轉(Inversion of Control)和門面模式(Facade),實際還有服務提供器(Service Providers)和別名(Alias),咱們建立本身的類庫和擴展 Laravel 都會方便不少。

這裏總結一下建立本身類庫的方法:

  1. 在 app/library/MyFoo 下建立類 MyFoo.php
  2. 在 app/library/MyFoo/providers 下建立 MyFooServiceProvider.php
  3. 在 app/library/MyFoo/facades 下建立 MyFooFacade.php
  4. 在 app/config/app.php 中添加 providers 和 aliases
相關文章
相關標籤/搜索