摘要:反射提供給面向對象編程可以自省的能力,即反射。在簡單工廠模式中,根據傳遞的參數來返回不同的類的實例簡單工廠模式又稱為靜態工廠方法模式。也就是簡單工廠模式工廠工廠類。
利用反射來實現工廠模式的生產而無需創建特定的工廠類
轉載請注明來源
[Relfection]
Reflection
Reflection
,即反射。反射提供給面向對象編程可以自省的能力PHP
提供了完整的反射 API
,提供了內省類、接口、函數、方法和擴展的能力。此外,反射 API
提供了方法來取出函數、類和方法中的文檔注釋。詳細見PHP官網
PHP反射簡介 Reflection
能干什么[protected/private]
,這些特性使得PHP的使用靈活性得到非常大的提高。例如:Laravel
框架的所謂優雅所在,即容器、依賴注入、IOC
控制反轉就是依靠這些特性實現的Hyperf
框架的注解路由也是根據反射獲得注釋來實現的生成文檔
因為反射可以獲取類屬性和方法的訪問權限,可以掃描整個項目的所有文件再使用反射來生成文檔測試驅動開發
利用反射獲取該類的所有方法的特性,進行測試驅動開發開發插件
利用反射獲取類的內部結構的特性,實現 Hook
功能,例如框架插件的實現Reflection
的優缺點優點
反射提供了對類的反解析,從而相比原本面向對象的編程方式獲得了極高的靈活性,以及合理的使用能夠讓代碼看起來更加優雅以及簡潔。原本在面向對象的編程方式中,使用一個類的實例需要先 new
出一個對象再使用方法,但是使用了反射機制,只需要提供一個該類的方法然后使用反射機制即可使用該對象或者方法。Laravel
框架正是使用了大量的反射才獲得了優雅的美譽,Swoole
的 Hyperf
框架的注解路由的實現也是使用了反射缺點
同時,由于反射是類實例化的反過程,破壞了面向對象的封裝性,直接將類的整個內部結構暴露,這就導致了反射一旦濫用,代碼將難于管理,整個項目將非常混亂,甚至導致業務執行錯亂。尤其在大項目幾十人的團隊中,試想一下,原本的面向對象,只告訴什么可以用,什么不可以用,CTO寫好了底層代碼,其他人繼承后然后使用就行,內部結構啥的其他人都不知道。一旦用上了反射,如果有一個程序員不小心將原本是 protected
或者是 private
的屬性或者方法設置成了可以訪問,其他程序員在不知情的情況調用了本該隱藏的數據或者方法,那將導致不可預測的災難【見下面示例代碼】IDE
中通過直接直接點擊代碼溯源,對于新手真的是很蛋疼,Laravel
和Hyperf
都是如此private
方法設置成外部可訪問#Example:setAccessible(true);echo $method->invoke(new Foo);// echos "7"?>
[簡單工廠模式] [工廠模式] [抽象工廠模式]
簡單工廠模式
又稱為靜態工廠方法模式。簡單的說,就是創建對象的方式是通過一個靜態方法來實現的。在簡單工廠模式中,根據傳遞的參數來返回不同的類的實例PHP
中在簡單工廠模式中,有一個抽象的產品類【即abstract class Calculate
】,這個抽象類可以是接口/抽象類/普通類
。這個抽象的產品類可以派生出多個具體的產品類【即class CalculateAdd
以及class CalculateSub
】。最后再由一個具體的工廠類【即class CalculateFactory
】來獲取所需要的產品類的實例//生產抽象類abstract class Calculate{ //數字A protected $number_a = null; //數字B protected $number_b = null; //設置數字A public function setNumberA( $number ){ $this->number_a = $number; } //設置數字B public function setNumberB( $number ){ $this->number_b = $number; } //獲取數字A public function getNumberA(){ return $this->number_a; } //獲取數字B public function getNumberB(){ return $this->number_b; } //獲取計算結果【獲取生產出的產品】 public function getResult(){ return null; }}
//加法運算class CalculateAdd extends Calculate{ //獲取運算結果【獲取具體的產品】 public function getResult(){ return $this->number_a + $this->number_b; }}//減法運算class CalculateSub extends Calculate{ //獲取運算結果【獲取具體的產品】 public function getResult(){ return $this->number_a - $this->number_b; }}//乘法 / 除法 等等其他運算【其他產品】
簡單工廠模式
php
中,實現的方式其實就一個 switch
函數或者是 php8
新出的 match
函數來實例化所需要的產品生產類//根據運算不同實例化不同的對象//【也就是根據所需產品,實例化對應的產品類進行生產】//對應的實現其實就是一個switch或者php8函數新出的match函數//下面用最新的match函數做演示class CalculateFactory{ public static function setCalculate( $type = null ){ return match( $type ){ add => (function(){ return new CalculateAdd(); })(), sub => (function(){ return new CalculateSub(); })(), default => null; }; } }//具體使用$calculate = CalculateFactory::setCalculate(add);$calculate->setNumberA = 1;$calculate->setNumberB = 2;//計算echo $calculate->getResult;//echo 3
總結
:簡單工廠模式其實就是創建一個基類【abstract
】,該類存放所有具體生產產品類的共用的代碼
,但是沒有執行過程
,然后具體生產產品的類全部繼承基類再實現各自的生產過程
。最后創建一個工廠類,該類用來根據傳入的參數
來獲取所需的生產類
工廠方法模式
又稱為工廠模式,屬于創造型模式。在工廠模式中,工廠類的父類只負責定義公共接口,并不執行實際的生產動作。實際的生產動作則交給工廠的子類來完成。這樣做將類的的實例化延遲到了工廠的子類,通過工廠的子類來完成實例化具體的產品,也就是生產interface CalculateFactory
】,可以是接口/抽象類
,這個抽象的工廠類可以派生出多個具體的工廠類【即FactoryAdd
以及FactorySub
】以下代碼需要用到上面的生產抽象類:abstract class Calculate
以及具體的生產類,即:CalculateAdd
以及 CalculateSub
。下面不再重復實現
interface CalculateFactory{ public function CreateCalculate(); }class FactoryAdd implements CalculateFactory{ public function CreateCalculate(){ return new CalculateAdd(); } }class FactorySub implements CalculateFactory{ public function CreateCalculate(){ return new CalculateSub(); } }//具體使用//創建工廠實例$calculateFactory = new FactoryAdd();$add = $calculateFactory->CreateCalculate();$add->setNumberA( 1 );$add->setNumberB( 2 );//計算echo $add->getResult();//echo 3
只有一個工廠
來生產對應的生產對象【即CalculateFactory
】。而在工廠模式中,每一個生產產對象都由自己的工廠
來生產,并且這些工廠都繼承
自同一個接口【即 interface CalculateFactory
】抽象工廠模式
抽象工廠模式提供創建一系列相關或相互依賴對象的接口,而且無需指定它們具體的類。這么理解很抽象。通俗一點的解釋就是,相比于上面的工廠模式來講,抽象工廠模式在每個不同的工廠之上又有一個超級工廠,這個超級工廠是抽象的接口【interface
】,用來生產具體的工廠abstract class Phone
以及abstract class Android
】,可以是接口/抽象類/普通類
,每個抽象產品類可以派生出多個具體產品類【即class IPhone
/ class MiPhone
以及 class IOS
/ class Android
】。一個抽象的工廠類【即interface AbstractFactory
】可以派生出多個具體的工廠類【即class iPhoneFactory
以及class MiFactory
】,且每個具體的工廠類可以創建多個產品類的實例【即都有createPhone
和createSystem
】//抽象的產品類abstract class Phone{}abstract class System{}//具體的產品類class IPhone extends Phone{}class MiPhone extends Phone{}//具體的產品類class IOS extends System{}class Android extends System{}//超級工廠interface AbstractFactory{ public function createPhone(); public function createSystem();}//具體的蘋果工廠class iPhoneFactory implements AbstractFactory{ //生產蘋果手機 public function createPhone(){ return new IPhone(); } //生產蘋果系統 public function createSystem(){ return new IOS(); }}//具體的小米工廠class MiFactory implements AbstractFactory{ //生產小米手機 public function createPhone(){ return new MiPhone(); } //生產安卓系統 public function createSystem(){ return new Android(); }}
AbstarctFactory
】一個抽象產品類(可以是:接口,抽象類,普通類),可以派生出多個具體產品類
多帶帶一個具體的工廠類
每個具體工廠類只能創建一個具體產品類的實例
一個抽象產品類(可以是:接口,抽象類,普通類),可以派生出多個具體產品類
一個抽象工廠類(可以是:接口,抽象類),可以派生出多個具體工廠類
每個具體工廠類只能創建一個具體產品類的實例
多個抽象產品類(可以是:接口,抽象類,普通類),每個抽象產品類可以派生出多個具體產品類
一個抽象工廠類(可以是:接口,抽象類),可以派生出多個具體工廠類
每個具體工廠類可以創建多個具體產品類的實例
簡單工廠模式只有一個抽象產品類,只有一個具體的工廠類
工廠方法模式只有一個抽象產品類,而抽象工廠模式有多個抽象產品類
工廠方法模式的具體工廠類只能創建一個具體產品類的實例,而抽象工廠模式可以創建多個具體產品類的實例
Laravel-admin
進行舉例先看下以下的代碼,需求背景:需要根據角色不同顯示不同的權限按鈕
inRoles([AdminUserModel::getAssignmentRole()])) { $grid->disableBatchActions(); $grid->disableEditButton(); $grid->disableCreateButton(); $grid->disableDeleteButton(); } elseif (Admin::user()->inRoles([AdminUserModel::getEvaluatorRole()])) { $grid->disableBatchActions(); $grid->disableEditButton(); $grid->disableCreateButton(); $grid->disableDeleteButton(); $grid->actions(function (Grid/Displayers/Actions $actions) { $actions->append(new ConfirmCloseTaskAction()); }); } else { $grid->disableCreateButton(); $grid->disableDeleteButton(); $grid->disableEditButton(); $grid->disableBatchActions(); $grid->disableViewButton(); $grid->disableActions(); } }}
Controller
的增加】以及角色的增加,需要寫更多重復的判斷以及重復的代碼抽象出一個產品類來派生出多個角色的權限產品類
抽象出一個工廠類來派生出多個具體的工廠類,這些工廠類表現為對應要使用權限按鈕的場景
每個具體工廠【使用權限按鈕的場景】可以創建多個具體產品類【即實例化多個角色的權限產品】
inRoles([$role]); } /** * 調用對應的方法 * [該方法其實就是工廠模式中的工廠,專門來生產的] * [多個工廠對應的就是各個需要用到Action權限的Controller控制器] * [每個Controller控制器來生產自己的Action權限] * [這個生產是通過反射來實現] * * @param Grid $grid * @param string $role * @param string $class * @throws /ReflectionException */ protected static function setRoleAction(Grid $grid, string $role, string $class) { $r = new /ReflectionClass($class); $methodName = $role . Action; if (!$r->hasMethod($methodName)) throw new /Exception(Method Not Found [ method : . $methodName . ] ); $method = $r->getMethod($methodName); $method->invoke($r->newInstance(), $grid); }}
showActions(); $grid->showViewButton(); } //在TaskController下有需要使用權限按鈕的角色 //財務角色 public function financeAction(Grid $grid) { $grid->showActions(); $grid->showViewButton(); } //在TaskController下有需要使用權限按鈕的角色 //業務員角色 public function salesmanAction(Grid $grid) { } //....其他角色}
TaskController
中控制權限的代碼直接優化成如下:【優雅了不少~
】inRoles([AdminUserModel::getAssignmentRole()])) { $grid->disableBatchActions(); $grid->disableEditButton(); $grid->disableCreateButton(); $grid->disableDeleteButton(); } elseif (Admin::user()->inRoles([AdminUserModel::getEvaluatorRole()])) { $grid->disableBatchActions(); $grid->disableEditButton(); $grid->disableCreateButton(); $grid->disableDeleteButton(); $grid->actions(function (Grid/Displayers/Actions $actions) { $actions->append(new ConfirmCloseTaskAction()); }); } else { $grid->disableCreateButton(); $grid->disableDeleteButton(); $grid->disableEditButton(); $grid->disableBatchActions(); $grid->disableViewButton(); $grid->disableActions(); } */ }}
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/123756.html
摘要:工廠模式,依賴轉移當然,實現控制反轉的方法有幾種。其實我們稍微改造一下這個類,你就明白,工廠類的真正意義和價值了。雖然如此,工廠模式依舊十分優秀,并且適用于絕大多數情況。 此篇文章轉載自laravel-china,chongyi的文章https://laravel-china.org/top...原文地址: http://www.insp.top/learn-lar... ,轉載務必保...
摘要:本文一大半內容都是通過舉例來讓讀者去理解什么是控制反轉和依賴注入,通過理解這些概念,來更加深入。這種由外部負責其依賴需求的行為,我們可以稱其為控制反轉。工廠模式,依賴轉移當然,實現控制反轉的方法有幾種。 容器,字面上理解就是裝東西的東西。常見的變量、對象屬性等都可以算是容器。一個容器能夠裝什么,全部取決于你對該容器的定義。當然,有這樣一種容器,它存放的不是文本、數值,而是對象、對象的描...
摘要:使用元數據包中包含了中每一個被建模類對應的接口。任何對象的元數據是使用的實現來表示的。加載模型的序列化形式是個在運行期間獲取元數據的有效方法。反射提供一個反射式,可以檢查對象的元數據以及一般地訪問和操縱數據。 使用元數據 Java包org.eclipse.emf.ecore中包含了Ecore中每一個被建模類對應的接口。任何EMF對象的元數據是使用Ecore的實現(implement...
摘要:提供了個常用的預定義接口,實現某些特定的能力。是啥如官方文檔所述,它提供像訪問數組一樣訪問對象的能力的接口。它提供了個接口我們實現這個接口,依次對應數組的讀取,設置,操作。用上了它,可以讓一個類即可以支持對象引用,也支持數組引用。 php提供了6個常用的預定義接口,實現某些特定的能力。其中最最常用的就是 ArrayAccess 了,像 Laravel 這種流行的框架都用到了它。 Arr...
近期在維護公司項目的時候遇到一個問題,因為實體類中的 set 方法涉及到了業務邏輯,因此在給對象賦值的過程中不能夠使用 set 方法,為了實現功能,所以采用了反射的機制給對象屬性賦值,借此機會也了解了反射的一些具體用法和使用場景,分以下兩點對反射進行分析: 反射的優勢和劣勢 反射的應用場景 反射的優勢和劣勢 ??個人理解,反射機制實際上就是上帝模式,如果說方法的調用是 Java 正確的打開方式...
閱讀 739·2023-04-25 19:43
閱讀 3983·2021-11-30 14:52
閱讀 3811·2021-11-30 14:52
閱讀 3872·2021-11-29 11:00
閱讀 3806·2021-11-29 11:00
閱讀 3905·2021-11-29 11:00
閱讀 3584·2021-11-29 11:00
閱讀 6193·2021-11-29 11:00