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

jopen 9年前發布 | 68K 次閱讀 Laravel Web框架

這兩個概念對于 Laravel 的使用者來說應該并不陌生,尤其是當你希望擴展或者替換 Laravel 核心庫的時候,理解和合理使用它們可以極大提升 Laravel 的戰斗力。這里以創建一個自己的 ServiceProvider 為例理解 Inversion of Control 和 Facade 在 Laravel 中的應用。

控制反轉(Inversion of Control)

什么是 IoC

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

</blockquote>

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

Laravel 中的使用

注入一個類:

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

這個例子的意思是創建一個別名為 foo 的類,使用時實際實例化的是 FooBar。

使用這個類的方法是:

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

$value 實際上是 FooBar 對象。

如果希望使用單例模式來實例化類,那么使用:

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

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

注入類的更多例子可以看 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;
    });
}

}</pre>

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

當我們執行下面代碼:

App::register('FooServiceProvider');

我們就完成一個注入了。但是這個還是得手動寫,所以怎么讓 Laravel 自己來做這事兒呢?

我們只要在 app/config/app.php 中的 providers 數組里面增加一行:

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

這樣我們就可以使用 App::make(‘foo’) 來實例化一個類了。

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

門面模式(Facade)

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

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

</blockquote>

Laravel 中的使用

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

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

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

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

use Illuminate\Support\Facades\Facade;

class Foo extends Facade {

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

}</pre>

這樣我們就可以通過 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
  5. </ol> 來源:閆肅的博客

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!