剛剛開始學(xué)Laravel就會(huì)接觸到路由
1 2 3 | Route::get( '/' , function () { return view( 'welcome' ); }); |
后來筆者一本正經(jīng)的去讀過Route類的代碼,驚訝的發(fā)現(xiàn)并沒有g(shù)et這個(gè)方法,之后了解到Laravel用了Facade模式。
Facade本質(zhì)上是一個(gè)“把工作推給別人做的”的類。
Facade存在的價(jià)值,可以從服務(wù)容器談起。服務(wù)容器,可見我的另一篇博文,地址:http://www.cnblogs.com/sweng/p/6430374.html
舉個(gè)例子,不知道大家以前寫代碼有沒有過obj->method(arg1,arg2)->func(arg3,arg4);的體驗(yàn)。學(xué)過服務(wù)容器的讀者知道,這行代碼就是把服務(wù)容器里的對(duì)象取出來,并調(diào)用他的方法。這對(duì)熟悉服務(wù)容器里注冊(cè)過哪些類的開發(fā)人員來說,這種代碼還是可以接受的。但是如果像路由定義那樣,也要寫成這樣冗長(zhǎng)的形式,實(shí)在太不優(yōu)雅了。所以用Facade模式可以很好的精簡(jiǎn)代碼長(zhǎng)度。
我們先寫一個(gè)DB類
1 2 3 4 5 6 7 8 9 10 11 12 | 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; } } |
數(shù)據(jù)庫(kù)讀寫是整個(gè)系統(tǒng)非常常用的操作。但是DB類會(huì)注冊(cè)在服務(wù)容器里,每次數(shù)據(jù)庫(kù)讀寫都要把DB類的對(duì)象從服務(wù)容器里取出,實(shí)在很不方便。
我們寫一個(gè)Facade類
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 ); } } |
要理解這個(gè)類,我們只要關(guān)注最后一個(gè)函數(shù),就是__callstatic魔術(shù)方法。這個(gè)方法就是Facade類型對(duì)象在調(diào)用他自身沒有定義過的函數(shù)時(shí),就會(huì)調(diào)用__callstatic方法,是一個(gè)“候選人”的角色。
我們?cè)俣x一個(gè)DBFacade類
1 2 3 4 5 | class DBFacade extends Facade{ public static function getFacadeAccessor(){ return API\DB:: class ; } } |
每一個(gè)Facade子類都要實(shí)現(xiàn)getFacadeAccessor方法,返回只是一個(gè)類名字符串,用來代入getInstance方法,來創(chuàng)建一個(gè)真正“做事情”的類。
此時(shí),F(xiàn)acade已經(jīng)可以用了,我們調(diào)用DBFacade的靜態(tài)方法
1 | DBFacade::Write( 'hello' ); |
閱讀代碼,我們發(fā)現(xiàn),其實(shí)DBFacade是沒有Write方法的,于是就調(diào)用他父類Facade的__callstatic魔術(shù)方法,魔術(shù)方法我們已經(jīng)在父類里面實(shí)現(xiàn)了。
以前聽過同行抱怨,PHP語(yǔ)法亂,難記。但實(shí)際上像魔術(shù)方法把Facade實(shí)現(xiàn)的非常簡(jiǎn)潔,可見語(yǔ)法設(shè)計(jì)的精妙。