国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PHP高級特性-反射Reflection以及Factory工廠設計模式的結合使用[代碼實例]

番茄西紅柿 / 3248人閱讀

摘要:反射提供給面向對象編程可以自省的能力,即反射。在簡單工廠模式中,根據傳遞的參數來返回不同的類的實例簡單工廠模式又稱為靜態工廠方法模式。也就是簡單工廠模式工廠工廠類。

PHP高級特性-反射以及工廠設計模式的結合使用 [結合 Laravel-Admin 代碼實例講解]

利用反射來實現工廠模式的生產而無需創建特定的工廠類

本文地址http://janrs.com/?p=833轉載無需經過作者本人授權

轉載請注明來源


反射[Relfection]

JANRS.COM - PHP Reflection 反射

什么是Reflection

Reflection,即反射。反射提供給面向對象編程可以自省的能力

這么理解有點太過于概念化,通俗地講,就是能根據事件的結果反查出原因。在編程中,可以根據一個被實例化的對象,反查出這個對象屬于的類以及該類擁有所有屬性以及方法,甚至可以讀取文檔注釋。這個反查的過程就叫做反射

PHP 提供了完整的反射 API ,提供了內省類、接口、函數、方法和擴展的能力。此外,反射 API 提供了方法來取出函數、類和方法中的文檔注釋。詳細見PHP官網 PHP反射簡介

Reflection能干什么

在上面講到的,可以使用反射來獲取一個類的所有屬性以及方法還有注釋文檔,甚至可以獲取類屬性和方法的訪問權限[protected/private],這些特性使得PHP的使用靈活性得到非常大的提高。例如:

- Laravel 框架的所謂優雅所在,即容器、依賴注入、IOC 控制反轉就是依靠這些特性實現的
- Hyperf 框架的注解路由也是根據反射獲得注釋來實現的
- 生成文檔 因為反射可以獲取類屬性和方法的訪問權限,可以掃描整個項目的所有文件再使用反射來生成文檔
- 測試驅動開發 利用反射獲取該類的所有方法的特性,進行測試驅動開發
- 開發插件 利用反射獲取類的內部結構的特性,實現 Hook 功能,例如框架插件的實現

Reflection的優缺點

優點 反射提供了對類的反解析,從而相比原本面向對象的編程方式獲得了極高的靈活性,以及合理的使用能夠讓代碼看起來更加優雅以及簡潔。原本在面向對象的編程方式中,使用一個類的實例需要先 new 出一個對象再使用方法,但是使用了反射機制,只需要提供一個該類的方法然后使用反射機制即可使用該對象或者方法。Laravel 框架正是使用了大量的反射才獲得了優雅的美譽,SwooleHyperf 框架的注解路由的實現也是使用了反射

缺點 同時,由于反射是類實例化的反過程,破壞了面向對象的封裝性,直接將類的整個內部結構暴露,這就導致了反射一旦濫用,代碼將難于管理,整個項目將非常混亂,甚至導致業務執行錯亂。尤其在大項目幾十人的團隊中,試想一下,原本的面向對象,只告訴什么可以用,什么不可以用,CTO寫好了底層代碼,其他人繼承后然后使用就行,內部結構啥的其他人都不知道。一旦用上了反射,如果有一個程序員不小心將原本是 protected 或者是 private 的屬性或者方法設置成了可以訪問,其他程序員在不知情的情況調用了本該隱藏的數據或者方法,那將導致不可預測的災難【見下面示例代碼】

其次,由于反射的靈活性極高,這導致了無法在 IDE 中通過直接直接點擊代碼溯源,對于新手真的是很蛋疼,LaravelHyperf 都是如此

在下面的代碼中,反射的機制直接將 private 方法設置成外部可訪問
#Example:setAccessible(true);echo $method->invoke(new Foo);// echos "7"?>

工廠設計模式

三種工廠設計模式 [簡單工廠模式] [工廠模式] [抽象工廠模式]

簡單工廠模式 又稱為靜態工廠方法模式。簡單的說,就是創建對象的方式是通過一個靜態方法來實現的。在簡單工廠模式中,根據傳遞的參數來返回不同的類的實例

PHP中在簡單工廠模式中,有一個抽象的產品類【即abstract class Calculate】,這個抽象類可以是接口/抽象類/普通類。這個抽象的產品類可以派生出多個具體的產品類【即class CalculateAdd以及class CalculateSub】。最后再由一個具體的工廠類【即class CalculateFactory】來獲取所需要的產品類的實例

JARNS.COM - 工廠模式[簡單工廠UML圖] JARNS.COM - 工廠模式[簡單工廠UML圖]

代碼實現

1) 抽象產品生產類:運算抽象類
//生產抽象類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;	}}
2) 具體產品生產類:加法運算 / 減法運算 等等
//加法運算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;	}}//乘法 / 除法 等等其他運算【其他產品】
3) 工廠:工廠類。即用一個多帶帶的類來創造實例化的過程,這個類就是工廠。也就是 簡單工廠模式
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

JARNS.COM - 工廠模式[工廠UML圖] JARNS.COM - 工廠模式[工廠UML圖]

代碼實現【以下代碼需要用到上面的生產抽象類】

以下代碼需要用到上面的生產抽象類: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】,且每個具體的工廠類可以創建多個產品類的實例【即都有createPhonecreateSystem

JARNS.COM - 抽象工廠模式[工廠UML圖] JARNS.COM - 抽象工廠模式[工廠UML圖]

代碼實現

//抽象的產品類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的增加】以及角色的增加,需要寫更多重復的判斷以及重復的代碼

解決思路:不同的角色需要擁有的不同的權限,每個角色都可以用一個固定的方法來設置權限,這個固定的方法可以為不同的角色設置權限。這些條件剛好滿足工廠模式的使用場景:即:

  • 抽象出一個產品類來派生出多個角色的權限產品類
  • 抽象出一個工廠類來派生出多個具體的工廠類,這些工廠類表現為對應要使用權限按鈕的場景
  • 每個具體工廠【使用權限按鈕的場景】可以創建多個具體產品類【即實例化多個角色的權限產品】

代碼如下【在下面的代碼中,將使用反射來代替工廠的生產】

1) 抽象出一個產品類來派生出多個角色的權限產品類
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);    }}

根據以上的反射來實現實例化的過程,上面的TaskController的權限可以簡化成下面的代碼:

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://janrs.com

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/123756.html

相關文章

  • php實現依賴注入(DI)和控制反轉(IOC)

    摘要:工廠模式,依賴轉移當然,實現控制反轉的方法有幾種。其實我們稍微改造一下這個類,你就明白,工廠類的真正意義和價值了。雖然如此,工廠模式依舊十分優秀,并且適用于絕大多數情況。 此篇文章轉載自laravel-china,chongyi的文章https://laravel-china.org/top...原文地址: http://www.insp.top/learn-lar... ,轉載務必保...

    tomato 評論0 收藏0
  • 深入理解控制反轉(IoC)和依賴注入(DI)

    摘要:本文一大半內容都是通過舉例來讓讀者去理解什么是控制反轉和依賴注入,通過理解這些概念,來更加深入。這種由外部負責其依賴需求的行為,我們可以稱其為控制反轉。工廠模式,依賴轉移當然,實現控制反轉的方法有幾種。 容器,字面上理解就是裝東西的東西。常見的變量、對象屬性等都可以算是容器。一個容器能夠裝什么,全部取決于你對該容器的定義。當然,有這樣一種容器,它存放的不是文本、數值,而是對象、對象的描...

    HollisChuang 評論0 收藏0
  • EMF學習筆記(二)——使用EMF編程——開發元數據

    摘要:使用元數據包中包含了中每一個被建模類對應的接口。任何對象的元數據是使用的實現來表示的。加載模型的序列化形式是個在運行期間獲取元數據的有效方法。反射提供一個反射式,可以檢查對象的元數據以及一般地訪問和操縱數據。 使用元數據   Java包org.eclipse.emf.ecore中包含了Ecore中每一個被建模類對應的接口。任何EMF對象的元數據是使用Ecore的實現(implement...

    Jiavan 評論0 收藏0
  • PHP高級特性】ArrayAccess 接口

    摘要:提供了個常用的預定義接口,實現某些特定的能力。是啥如官方文檔所述,它提供像訪問數組一樣訪問對象的能力的接口。它提供了個接口我們實現這個接口,依次對應數組的讀取,設置,操作。用上了它,可以讓一個類即可以支持對象引用,也支持數組引用。 php提供了6個常用的預定義接口,實現某些特定的能力。其中最最常用的就是 ArrayAccess 了,像 Laravel 這種流行的框架都用到了它。 Arr...

    mrli2016 評論0 收藏0
  • Reflection:Java反射機制應用場景

    近期在維護公司項目的時候遇到一個問題,因為實體類中的 set 方法涉及到了業務邏輯,因此在給對象賦值的過程中不能夠使用 set 方法,為了實現功能,所以采用了反射的機制給對象屬性賦值,借此機會也了解了反射的一些具體用法和使用場景,分以下兩點對反射進行分析: 反射的優勢和劣勢 反射的應用場景 反射的優勢和劣勢 ??個人理解,反射機制實際上就是上帝模式,如果說方法的調用是 Java 正確的打開方式...

    浠ラ箍 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<