剛剛開始學Laravel就會接觸到路由php
Route::get('/', function () { return view('welcome'); });
後來筆者一本正經的去讀過Route類的代碼,驚訝的發現並無get這個方法,以後瞭解到Laravel用了Facade模式。html
Facade本質上是一個「把工做推給別人作的」的類。數據庫
Facade存在的價值,能夠從服務容器談起。服務容器,可見個人另外一篇博文,地址:http://www.cnblogs.com/sweng/p/6430374.html函數
舉個例子,不知道你們之前寫代碼有沒有過obj->method(arg1,arg2)->func(arg3,arg4);的體驗。學過服務容器的讀者知道,這行代碼就是把服務容器裏的對象取出來,並調用他的方法。這對熟悉服務容器裏註冊過哪些類的開發人員來講,這種代碼仍是能夠接受的。可是若是像路由定義那樣,也要寫成這樣冗長的形式,實在太不優雅了。因此用Facade模式能夠很好的精簡代碼長度。spa
咱們先寫一個DB類設計
namespace API; class DB{ public function __construct($args){ } public function Write($str){ echo 'Write:'.$str.PHP_EOL; } public function Read($str){ echo 'Read:'.$str.PHP_EOL; } }
數據庫讀寫是整個系統很是經常使用的操做。可是DB類會註冊在服務容器裏,每次數據庫讀寫都要把DB類的對象從服務容器裏取出,實在很不方便。htm
咱們寫一個Facade類對象
class Facade{ public function __construct(){ // } public static function getInstance($classname,$args){ return new $classname($args); } public static function getFacadeAccessor(){ // } public static function __callstatic($method,$arg){ $instance=static::getInstance(static::getFacadeAccessor(),[1,2,3]); return call_user_func_array(array($instance,$method),$arg); } }
要理解這個類,咱們只要關注最後一個函數,就是__callstatic魔術方法。這個方法就是Facade類型對象在調用他自身沒有定義過的函數時,就會調用__callstatic方法,是一個「候選人」的角色。blog
咱們再定義一個DBFacade類路由
class DBFacade extends Facade{ public static function getFacadeAccessor(){ return API\DB::class; } }
每個Facade子類都要實現getFacadeAccessor方法,返回只是一個類名字符串,用來代入getInstance方法,來建立一個真正「作事情」的類。
此時,Facade已經能夠用了,咱們調用DBFacade的靜態方法
DBFacade::Write('hello');
閱讀代碼,咱們發現,其實DBFacade是沒有Write方法的,因而就調用他父類Facade的__callstatic魔術方法,魔術方法咱們已經在父類裏面實現了。
之前聽過同行抱怨,PHP語法亂,難記。但實際上像魔術方法把Facade實現的很是簡潔,可見語法設計的精妙。