深刻解析tp5.1與laravel 中Facade底層原理實現php
1. 什麼是Facadehtml
2. 爲何須要有什麼好處laravel
3. Facade實現原理thinkphp
4. 功能實現、app
5. 容器注入框架
專業解釋:工具
門面模式(Facade)又稱外觀模式,用於爲子系統中的一組接口提供一個一致的界面。門面模式定義了一個高層接口,這個接口使得子系統更加容易使用:引入門面角色以後,用戶只須要直接與門面角色交互,用戶與子系統之間的複雜關係由門面角色來實現,從而下降了系統的耦合度。測試
通俗解釋:spa
門面爲容器中的類提供了一個靜態調用接口,相比於傳統的靜態方法調用, 帶來了更好的可測試性和擴展性,你能夠爲任何的非靜態類庫定義一個facade類。3d
對於一個非靜態的類,若是要調用這個類的方法咱們可能就是要經過new 建立這個對象,而後再經過 -> 調用這個類的方法
如:
咱們要調用這個類的方法就是
這樣調用類,可是若是調用的次數多了,本身每次調用這方法都要建立類從寫法上就以爲不是很好而咱們更多的是想直接以靜態經過類名::方法() 的方式調用,而且開發速度不快以及不夠優雅,
而若是咱們使用facade模式
給這個類一個靜態代理對象,而後咱們就能夠經過靜態的方式調用
固然如上是TP5手冊的例子
首先咱們能夠建立一個工具類UserUtil
若是說咱們須要使用這個類的時候,好比:在index控制器中進行調用UserUtil中的index方法
如上代碼,這就是咱們通常的操做方式。
這樣咱們就會看起來不夠的優雅。我在使用的時候還須要new出這個對象,我不想new怎麼辦?
咱們修改一下UserUtil中的index方法,用static修飾
而後在控制器中,就能夠經過類名的方式靜態的調用了
可是實際上這樣並非很好,若是說咱們的UserUtil中會定義不少方法,若是說咱們的Util中不止一個UserUtil,好比有TreeUtil等等其餘類,這個時候咱們就須要一一的給這些類定義static很明顯就不夠優雅,同時在內存中會一直保存這些靜態屬性,有不少使用其實次數很少可是也會保存很顯然會佔用一部分空間和資源。
其實還有一個最大的問題就是擴展和維護不強。
好比咱們在作項目的時候咱們在1.0版本的時候咱們可能會在index方法添加不少代碼,同時又有不少其餘的方法,但是有一天產品經理須要改需求,這個時候你發現你定義的這個類沒用了不知足這個需求的時候那麼咱們就只有需改源碼
那麼接下來咱們就須要對於這個UserUtil中的方法需改,但是當需改一個類的時間比一個新建一個類的時間要多的時候最好的辦法就是重寫。這個時候咱們可能在接下來的操做中要需改不少調用這個UserUtil的地方。腫麼辦??
咱們就可使用façade做爲這種類代理。
首先:咱們先把UserUtil類中的index需改回來
而後建立一個app\facade\UserUtil.php的門面代理類
在類中繼承Facade,同時重寫think\Facade類中的getFacadeClass方法
在方法中return的值就是 這個類要代理的實際類 你也能夠是
return 「app\util\UserUtil」;
只是那樣能夠顯得高大上哈哈哈~~~
而後咱們在控制器中使用
注意!引入的是app\facade\UserUtil
而後就成功了。
在代理類中除了重寫getFacadeClass方法外還可使用think\Facade的bind方法
首先咱們一塊兒看一下tp5.1對於框架是怎麼對於核心類庫用facade代理的
打開thinkphp\base.php這個文件,就能夠發現tp5.1的核心類庫是經過Think\Facade中的bind方法進行了定義
同時又經過Think\Loader中的addClassAlias方法對於核心類別名註冊
那麼咱們也能夠模仿
首先把app\facade\UserUtil類進行處理
不重寫getFacadeClass方法
而後咱們在app\common.php中寫
而後使用
Success
執行User::index()時
會進入think\Facade類中
由於沒有實際調用的方法這個時候執行__callStatic
經過createFacade建立實際被代理類的實例
首先判斷是否建立過
執行子類重寫的定義被代理類的方法
若是沒有重寫定義這個被代理類的地址
這個時候就檢查是否被綁定
重邦定的$bind中獲取實例
建立實例並執行實例的方法
原文出處:https://www.cnblogs.com/wadhf/p/11908653.html