PHP Laravel 的 Facade 的理解

栏目: PHP · 发布时间: 7年前

内容简介:在一般情況咱們如果要使用物件的某個方法可能會寫成如下 :但是有時後你會看到如下的程式碼 :而這就是 Laravel 所提供的 Facade 語法糖,而 Facade 實際上是一種設計模式。
PHP Laravel 的 Facade 的理解

什麼是 Laravel Facade ?

在一般情況咱們如果要使用物件的某個方法可能會寫成如下 :

<?php

$userService = $app->make('UserService');
$userService->createUser();

但是有時後你會看到如下的程式碼 :

<?php

UserService::createUser();

而這就是 Laravel 所提供的 Facade 語法糖,而 Facade 實際上是一種設計模式。

Facade(外觀) 設計模式

Facade 設計模式基本的定義如下 :

定義一個高層級的接口,客戶端只能透過它來與子系統進行溝通。

畫成概念圖大概長的如下,客戶端當要使用某個子系統所提供的功能時,不會直接去使用,而是會透過 Facade 來進行操作。

PHP Laravel 的 Facade 的理解

程式碼範例

假設咱們現在有個功能是用使用 LineSDK 來將訊息推送到 Line 取,然後咱們假設 sdk 的程式碼如下。

<?php

interface IMessage 
{
    public function push();
}


class LineSDK implements IMessage 
{
    public function push()
    {
        var_dump('I push a message to line');
    }
}

然後我們這裡會在寫一個 Facade 來讓我們的系統來使用。

<?php
class MessageFacade
{
    private $sdk; 

    public function __construct(IMessage $sdk)
    {
        $this->sdk = $sdk;
    }

    public function push()
    {
        $this->sdk->push();
    }
}

最後這個時候客戶端想要使用時,就會透過 Facade 來進行發送訊息,如下程式碼。

<?php

// 備註,在 laravel 時這裡嚴格來說會寫成
// $app->make('Imessage')
// 而不會看到 linesdk 這東西
$sdk = new MessageFacade(new LineSDK());
$sdk->push();

這樣有什麼好處 ?

當 sdk 進行修改時,你就不需要修改應用層的也方,只要修改 Facade 就好。

但這樣還是要改啊 ? 只是換個地方改而以 ?

那假設你有十個地方直接使用 SDK 呢 ? 那這樣不就代表你十個地方就要改,而如果使用 Facade 就只有一個地方要修改。

Laravel Facade 是如何實現的呢 ?

就單來說,它就如下圖所示,主要的核心就是在 Facade 這個抽象類別,它裡面會定義一個 php__callStatic 方法,它被執行到的時機為,這個類別中被呼叫靜態方法時,他就會被執行到。

PHP Laravel 的 Facade 的理解
<?php

abstract class Facade {
    public static function __callStatic($method, $args)
    {
        $instance = static::getFacadeAccessor();
        return $instance::$method(...$args);
    }
}
<?php

class MessageFacade extends Facade
{
    protected static function getFacadeAccessor(){
        return new LineSDK(); 
    }
}

class LineSDK 
{
    public function push()
    {
        var_dump('I push a message to line');
    }
}
<?php

include 'Facades/MessageFacade.php';

MessageFacade::push();

Laravel Facade 的爭論

它們的爭論點就是 :

是否要使用 Laravel Facade

這裡大至上會分成兩派 :

使用 Laravel Facade

這一派的程式碼會寫的如下 :

<?php
class Log
{
  
    public function __construct()
    {
    }

    public function send(log): void
    {
        LogService::send(log);
    }  
}

不使用 Laravel Facade

而這一派的程式碼會寫的如下 :

<?php

class Log
{
    private ILogService $logService;
  
    public function __construct(ILogService $logService)
    {
      $this->logService = $logService;
    }

    public function send(log): void
    {
      $this->logService->send(log);
    }  
}

支持與反對的看法

首先支持使用 Facade 這一派的他們提出以下使用後的優點 :

  1. 簡潔的程式碼。
  2. 乾淨的建構子。
  3. 更高的可測試性與彈性。

但相對的反對派提出了一下問題 :

  1. 相依了 Facade,這樣事實上就打破了當初建立 container 來想解決的事情。
  2. 要知道這個類別中有使用那些外部套件,那就只能一個一個找。
  3. IDE 的不友好。

順到說一下,就我各人的看法我比較偏向不使用 Laravel Facade,主要是因為我比較在意一個類別的相依性控制,而每當我需要知道這個類別有啥相依時,不用讓我一個一個去慢慢的找,對我來說有點浪費時間。

順到說一下,在下面的參考資料裡包含了大部份吵架的文章,有興趣的人可以去看看。

備註 : 關於使用 Laravel Facade 有更高的可測試性說明

在 Laravel Facade 中,如果你有一段程式碼直接的使用 Laravel Facade 如下 :

<?php

public function getIndex()
{
    Event::fire('foo', ['name' => 'Dayle']);

    return 'All done!';
}

然後你這時要進行測試時,可以使用 shouldReceive 的方法來模擬 Event :

<?php

public function testGetIndex()
{
    Event::shouldReceive('fire')->once()->with('foo', ['name' => 'Dayle']);

    $this->call('GET', '/');
}

參考資料


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First HTML and CSS

Head First HTML and CSS

Elisabeth Robson、Eric Freeman / O'Reilly Media / 2012-9-8 / USD 39.99

Tired of reading HTML books that only make sense after you're an expert? Then it's about time you picked up Head First HTML and really learned HTML. You want to learn HTML so you can finally create th......一起来看看 《Head First HTML and CSS》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换