内容简介:在一般情況咱們如果要使用物件的某個方法可能會寫成如下 :但是有時後你會看到如下的程式碼 :而這就是 Laravel 所提供的 Facade 語法糖,而 Facade 實際上是一種設計模式。
什麼是 Laravel Facade ?
在一般情況咱們如果要使用物件的某個方法可能會寫成如下 :
<?php $userService = $app->make('UserService'); $userService->createUser();
但是有時後你會看到如下的程式碼 :
<?php UserService::createUser();
而這就是 Laravel 所提供的 Facade 語法糖,而 Facade 實際上是一種設計模式。
Facade(外觀) 設計模式
Facade 設計模式基本的定義如下 :
定義一個高層級的接口,客戶端只能透過它來與子系統進行溝通。
畫成概念圖大概長的如下,客戶端當要使用某個子系統所提供的功能時,不會直接去使用,而是會透過 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 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 這一派的他們提出以下使用後的優點 :
- 簡潔的程式碼。
- 乾淨的建構子。
- 更高的可測試性與彈性。
但相對的反對派提出了一下問題 :
- 相依了 Facade,這樣事實上就打破了當初建立 container 來想解決的事情。
- 要知道這個類別中有使用那些外部套件,那就只能一個一個找。
- 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', '/'); }
參考資料
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 理解原型其实是理解原型链
- 要理解深度学习,必须突破常规视角去理解优化
- 深入理解java虚拟机(1) -- 理解HotSpot内存区域
- 荐 【C++100问】深入理解理解顶层const和底层const
- 深入理解 HTTPS
- 深入理解 HTTPS
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。