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

資訊專欄INFORMATION COLUMN

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

番茄西紅柿 / 3229人閱讀

摘要:反射提供給面向?qū)ο缶幊炭梢宰允〉哪芰Γ捶瓷洹T诤唵喂S模式中,根據(jù)傳遞的參數(shù)來返回不同的類的實例簡單工廠模式又稱為靜態(tài)工廠方法模式。也就是簡單工廠模式工廠工廠類。

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

利用反射來實現(xiàn)工廠模式的生產(chǎn)而無需創(chuàng)建特定的工廠類

本文地址http://janrs.com/?p=833轉(zhuǎn)載無需經(jīng)過作者本人授權(quán)

轉(zhuǎn)載請注明來源


反射[Relfection]

JANRS.COM - PHP Reflection 反射

什么是Reflection

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

PHP 提供了完整的反射 API ,提供了內(nèi)省類、接口、函數(shù)、方法和擴(kuò)展的能力。此外,反射 API 提供了方法來取出函數(shù)、類和方法中的文檔注釋。詳細(xì)見PHP官網(wǎng) PHP反射簡介

Reflection能干什么

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

- Laravel 框架的所謂優(yōu)雅所在,即容器、依賴注入、IOC 控制反轉(zhuǎn)就是依靠這些特性實現(xiàn)的
- Hyperf 框架的注解路由也是根據(jù)反射獲得注釋來實現(xiàn)的
- 生成文檔 因為反射可以獲取類屬性和方法的訪問權(quán)限,可以掃描整個項目的所有文件再使用反射來生成文檔
- 測試驅(qū)動開發(fā) 利用反射獲取該類的所有方法的特性,進(jìn)行測試驅(qū)動開發(fā)
- 開發(fā)插件 利用反射獲取類的內(nèi)部結(jié)構(gòu)的特性,實現(xiàn) Hook 功能,例如框架插件的實現(xiàn)

Reflection的優(yōu)缺點

優(yōu)點 反射提供了對類的反解析,從而相比原本面向?qū)ο蟮木幊谭绞将@得了極高的靈活性,以及合理的使用能夠讓代碼看起來更加優(yōu)雅以及簡潔。原本在面向?qū)ο蟮木幊谭绞街校褂靡粋€類的實例需要先 new 出一個對象再使用方法,但是使用了反射機(jī)制,只需要提供一個該類的方法然后使用反射機(jī)制即可使用該對象或者方法。Laravel 框架正是使用了大量的反射才獲得了優(yōu)雅的美譽,SwooleHyperf 框架的注解路由的實現(xiàn)也是使用了反射

缺點 同時,由于反射是類實例化的反過程,破壞了面向?qū)ο蟮姆庋b性,直接將類的整個內(nèi)部結(jié)構(gòu)暴露,這就導(dǎo)致了反射一旦濫用,代碼將難于管理,整個項目將非常混亂,甚至導(dǎo)致業(yè)務(wù)執(zhí)行錯亂。尤其在大項目幾十人的團(tuán)隊中,試想一下,原本的面向?qū)ο螅桓嬖V什么可以用,什么不可以用,CTO寫好了底層代碼,其他人繼承后然后使用就行,內(nèi)部結(jié)構(gòu)啥的其他人都不知道。一旦用上了反射,如果有一個程序員不小心將原本是 protected 或者是 private 的屬性或者方法設(shè)置成了可以訪問,其他程序員在不知情的情況調(diào)用了本該隱藏的數(shù)據(jù)或者方法,那將導(dǎo)致不可預(yù)測的災(zāi)難【見下面示例代碼】

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

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

工廠設(shè)計模式

三種工廠設(shè)計模式 [簡單工廠模式] [工廠模式] [抽象工廠模式]

簡單工廠模式 又稱為靜態(tài)工廠方法模式。簡單的說,就是創(chuàng)建對象的方式是通過一個靜態(tài)方法來實現(xiàn)的。在簡單工廠模式中,根據(jù)傳遞的參數(shù)來返回不同的類的實例

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

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

代碼實現(xiàn)

1) 抽象產(chǎn)品生產(chǎn)類:運算抽象類
//生產(chǎn)抽象類abstract class Calculate{		//數(shù)字A	protected $number_a = null;		//數(shù)字B	protected $number_b = null;		//設(shè)置數(shù)字A	public function setNumberA( $number ){		$this->number_a = $number;	}		//設(shè)置數(shù)字B	public function setNumberB( $number ){		$this->number_b = $number;	}		//獲取數(shù)字A	public function getNumberA(){		return $this->number_a;	}		//獲取數(shù)字B	public function getNumberB(){		return $this->number_b;	}		//獲取計算結(jié)果【獲取生產(chǎn)出的產(chǎn)品】	public function getResult(){		return null;	}}
2) 具體產(chǎn)品生產(chǎn)類:加法運算 / 減法運算 等等
//加法運算class CalculateAdd extends Calculate{		//獲取運算結(jié)果【獲取具體的產(chǎn)品】	public function getResult(){		return $this->number_a + $this->number_b;	}}//減法運算class CalculateSub extends Calculate{		//獲取運算結(jié)果【獲取具體的產(chǎn)品】	public function getResult(){		return $this->number_a - $this->number_b;	}}//乘法 / 除法 等等其他運算【其他產(chǎn)品】
3) 工廠:工廠類。即用一個多帶帶的類來創(chuàng)造實例化的過程,這個類就是工廠。也就是 簡單工廠模式
php 中,實現(xiàn)的方式其實就一個 switch 函數(shù)或者是 php8 新出的 match 函數(shù)來實例化所需要的產(chǎn)品生產(chǎn)類
//根據(jù)運算不同實例化不同的對象//【也就是根據(jù)所需產(chǎn)品,實例化對應(yīng)的產(chǎn)品類進(jìn)行生產(chǎn)】//對應(yīng)的實現(xiàn)其實就是一個switch或者php8函數(shù)新出的match函數(shù)//下面用最新的match函數(shù)做演示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
總結(jié):簡單工廠模式其實就是創(chuàng)建一個基類【abstract】,該類存放所有具體生產(chǎn)產(chǎn)品類的共用的代碼,但是沒有執(zhí)行過程,然后具體生產(chǎn)產(chǎn)品的類全部繼承基類再實現(xiàn)各自的生產(chǎn)過程。最后創(chuàng)建一個工廠類,該類用來根據(jù)傳入的參數(shù)來獲取所需的生產(chǎn)類

工廠方法模式 又稱為工廠模式,屬于創(chuàng)造型模式。在工廠模式中,工廠類的父類只負(fù)責(zé)定義公共接口,并不執(zhí)行實際的生產(chǎn)動作。實際的生產(chǎn)動作則交給工廠的子類來完成。這樣做將類的的實例化延遲到了工廠的子類,通過工廠的子類來完成實例化具體的產(chǎn)品,也就是生產(chǎn)

在工廠模式中,跟簡單工廠模式不一樣的是,有一個抽象的工廠類【即interface CalculateFactory】,可以是接口/抽象類,這個抽象的工廠類可以派生出多個具體的工廠類【即FactoryAdd以及FactorySub

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

代碼實現(xiàn)【以下代碼需要用到上面的生產(chǎn)抽象類】

以下代碼需要用到上面的生產(chǎn)抽象類:abstract class Calculate
以及具體的生產(chǎn)類,即:CalculateAdd 以及 CalculateSub。下面不再重復(fù)實現(xiàn)

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();	}	}//具體使用//創(chuàng)建工廠實例$calculateFactory = new FactoryAdd();$add = $calculateFactory->CreateCalculate();$add->setNumberA( 1 );$add->setNumberB( 2 );//計算echo $add->getResult();//echo 3
總結(jié):工廠模式相比于簡單工廠模式的區(qū)別在于,在簡單工廠模式中,只有一個工廠來生產(chǎn)對應(yīng)的生產(chǎn)對象【即CalculateFactory】。而在工廠模式中,每一個生產(chǎn)產(chǎn)對象都由自己的工廠來生產(chǎn),并且這些工廠都繼承自同一個接口【即 interface CalculateFactory

抽象工廠模式 抽象工廠模式提供創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而且無需指定它們具體的類。這么理解很抽象。通俗一點的解釋就是,相比于上面的工廠模式來講,抽象工廠模式在每個不同的工廠之上又有一個超級工廠,這個超級工廠是抽象的接口【interface】,用來生產(chǎn)具體的工廠

在抽象工廠模式中,有多個抽象的產(chǎn)品類【即abstract class Phone以及abstract class Android】,可以是接口/抽象類/普通類,每個抽象產(chǎn)品類可以派生出多個具體產(chǎn)品類【即class IPhone / class MiPhone 以及 class IOS / class Android】。一個抽象的工廠類【即interface AbstractFactory】可以派生出多個具體的工廠類【即class iPhoneFactory以及class MiFactory】,且每個具體的工廠類可以創(chuàng)建多個產(chǎn)品類的實例【即都有createPhonecreateSystem

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

代碼實現(xiàn)

//抽象的產(chǎn)品類abstract class Phone{}abstract class System{}//具體的產(chǎn)品類class IPhone extends Phone{}class MiPhone extends Phone{}//具體的產(chǎn)品類class IOS extends System{}class Android extends System{}//超級工廠interface AbstractFactory{	public function createPhone();	public function createSystem();}//具體的蘋果工廠class iPhoneFactory implements AbstractFactory{		//生產(chǎn)蘋果手機(jī)	public function createPhone(){		return new IPhone();	}		//生產(chǎn)蘋果系統(tǒng)	public function createSystem(){		return new IOS();	}}//具體的小米工廠class MiFactory implements AbstractFactory{		//生產(chǎn)小米手機(jī)	public function createPhone(){		return new MiPhone();	}		//生產(chǎn)安卓系統(tǒng)	public function createSystem(){		return new Android();	}}
總結(jié):抽象工廠模式相比于工廠模式,抽象工廠模式提供了一個接口用來規(guī)定所需要生產(chǎn)的產(chǎn)品。每個繼承于該接口的工廠都能按照指定的模式就行生產(chǎn)【代碼中的AbstarctFactory

以上三種工廠模式,最終都是為了將重復(fù)的代碼提取出來,并且按照特定的需求場景歸納好,進(jìn)行解耦和復(fù)用,以便在需要的場景中直接使用

三種模式的概括為:

簡單工廠:

  • 一個抽象產(chǎn)品類(可以是:接口,抽象類,普通類),可以派生出多個具體產(chǎn)品類
  • 多帶帶一個具體的工廠類
  • 每個具體工廠類只能創(chuàng)建一個具體產(chǎn)品類的實例

工廠模式:

  • 一個抽象產(chǎn)品類(可以是:接口,抽象類,普通類),可以派生出多個具體產(chǎn)品類
  • 一個抽象工廠類(可以是:接口,抽象類),可以派生出多個具體工廠類
  • 每個具體工廠類只能創(chuàng)建一個具體產(chǎn)品類的實例

抽象工廠:

  • 多個抽象產(chǎn)品類(可以是:接口,抽象類,普通類),每個抽象產(chǎn)品類可以派生出多個具體產(chǎn)品類
  • 一個抽象工廠類(可以是:接口,抽象類),可以派生出多個具體工廠類
  • 每個具體工廠類可以創(chuàng)建多個具體產(chǎn)品類的實例

三個模式之間的區(qū)別:

  • 簡單工廠模式只有一個抽象產(chǎn)品類,只有一個具體的工廠類
  • 工廠方法模式只有一個抽象產(chǎn)品類,而抽象工廠模式有多個抽象產(chǎn)品類
  • 工廠方法模式的具體工廠類只能創(chuàng)建一個具體產(chǎn)品類的實例,而抽象工廠模式可以創(chuàng)建多個具體產(chǎn)品類的實例

工廠模式與反射的結(jié)合使用

可以利用反射的特性來實現(xiàn)工廠模式的生產(chǎn)過程,結(jié)合Laravel-admin進(jìn)行舉例

先看下以下的代碼,需求背景:需要根據(jù)角色不同顯示不同的權(quán)限按鈕

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();            }    }}

以上的代碼很明顯一看就顯得很臃腫。且隨著業(yè)務(wù)的增加【即Controller的增加】以及角色的增加,需要寫更多重復(fù)的判斷以及重復(fù)的代碼

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

  • 抽象出一個產(chǎn)品類來派生出多個角色的權(quán)限產(chǎn)品類
  • 抽象出一個工廠類來派生出多個具體的工廠類,這些工廠類表現(xiàn)為對應(yīng)要使用權(quán)限按鈕的場景
  • 每個具體工廠【使用權(quán)限按鈕的場景】可以創(chuàng)建多個具體產(chǎn)品類【即實例化多個角色的權(quán)限產(chǎn)品】

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

1) 抽象出一個產(chǎn)品類來派生出多個角色的權(quán)限產(chǎn)品類
inRoles([$role]);    }    /**     * 調(diào)用對應(yīng)的方法     * [該方法其實就是工廠模式中的工廠,專門來生產(chǎn)的]     * [多個工廠對應(yīng)的就是各個需要用到Action權(quán)限的Controller控制器]     * [每個Controller控制器來生產(chǎn)自己的Action權(quán)限]     * [這個生產(chǎn)是通過反射來實現(xiàn)]     *     * @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);    }}

根據(jù)以上的反射來實現(xiàn)實例化的過程,上面的TaskController的權(quán)限可以簡化成下面的代碼:

showActions();        $grid->showViewButton();    }	//在TaskController下有需要使用權(quán)限按鈕的角色	//財務(wù)角色    public function financeAction(Grid $grid)    {		$grid->showActions();        $grid->showViewButton();    }	//在TaskController下有需要使用權(quán)限按鈕的角色	//業(yè)務(wù)員角色    public function salesmanAction(Grid $grid)    {    }		//....其他角色}

經(jīng)過使用設(shè)計模式封裝后,上面TaskController中控制權(quán)限的代碼直接優(yōu)化成如下:【優(yōu)雅了不少~

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();            }			*/    }}

總結(jié):設(shè)計模式以及反射通常在寫框架的時候用的比較多。但是在項目中,適當(dāng)?shù)氖褂迷O(shè)計模式以及反射,能夠讓代碼更加健壯以及可擴(kuò)展,也很優(yōu)雅~

歡迎來我的博客逛一逛 楊建勇的個人博客http://janrs.com

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/123756.html

相關(guān)文章

  • php實現(xiàn)依賴注入(DI)和控制反轉(zhuǎn)(IOC)

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

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

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

    HollisChuang 評論0 收藏0
  • EMF學(xué)習(xí)筆記(二)——使用EMF編程——開發(fā)元數(shù)據(jù)

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

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

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

    mrli2016 評論0 收藏0
  • Reflection:Java反射機(jī)制應(yīng)用場景

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

    浠ラ箍 評論0 收藏0

發(fā)表評論

0條評論

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