摘要:難道,就沒(méi)有強(qiáng)類(lèi)型特征答案是明確的,肯定有其實(shí)是一種強(qiáng)類(lèi)型和弱類(lèi)型的結(jié)合體。強(qiáng)類(lèi)型語(yǔ)言中,編譯器通常提供編譯檢查錯(cuò)誤的功能,它也是非常有用的。與此同時(shí),強(qiáng)類(lèi)型的代碼看起來(lái)也是很生硬的。
聲明:本文并非博主原創(chuàng),而是來(lái)自對(duì)《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當(dāng)然也不是原汁原味的翻譯,能保證90%的原汁性,另外因?yàn)槭抢斫夥g,肯定會(huì)有錯(cuò)誤的地方,歡迎指正。
歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處,謝謝!
接口約定 強(qiáng)類(lèi)型和弱類(lèi)型Water Fowl 這里我不知道該怎么翻譯,按理解就將他翻譯成弱類(lèi)型?
之前的文章中,涵蓋了依賴注入的基礎(chǔ)知識(shí):什么是依賴注入;如何實(shí)現(xiàn);以及他有什么好處。在舉例的代碼中,也展示了如何將接口注入到類(lèi)之中。在我們繼續(xù)深入之前,有必要深入一下接口相關(guān)的內(nèi)容,因?yàn)楹芏郟HP開(kāi)發(fā)人員對(duì)接口都有相當(dāng)程度的不熟練。
在我成為一個(gè)PHP程序員之前,我是寫(xiě).NET的。難道我喜歡痛苦或者其他什么的么?在.NET中接口無(wú)處不在,事實(shí)上.NET框架的很多核心內(nèi)容就是接口,還有一個(gè)好處:很多象.NET的語(yǔ)言如C#、VB等都是_強(qiáng)類(lèi)型_的。通常,傳入方法的原生對(duì)象,必須預(yù)先定義好相關(guān)的_類(lèi)型_。例如下面的C#代碼:
public int BillUser(User user) { this.biller.bill(user.GetId(), this.amount) }
我們不僅定義了傳入?yún)?shù)的_類(lèi)型_,函數(shù)返回的類(lèi)型都是已經(jīng)定義好的。C#提倡_安全類(lèi)型_。函數(shù)BillUser方法傳入的參數(shù)必須是User對(duì)象。
PHP是一種_弱類(lèi)型_語(yǔ)言。在弱類(lèi)型語(yǔ)言中,對(duì)象中可用的方法取決于其方法的使用形式,而非方法繼承或者實(shí)現(xiàn)的位置。例如:
public function billUser($user) { $this->biller->bill($user->getId(), $this->amount); }
我們無(wú)需告訴方法類(lèi)型的參數(shù)是什么,我們可以傳入任意對(duì)象,只要他有getId方法就行。這就是弱類(lèi)型編碼的例子。如果一個(gè)東西看起來(lái)象鴨子,叫聲也象,那么他就是一個(gè)鴨子。換言之,如果一個(gè)對(duì)象象user,行為也象user,那么他就是一個(gè)user對(duì)象。
難道,PHP就沒(méi)有強(qiáng)類(lèi)型特征?答案是明確的,肯定有!PHP其實(shí)是一種強(qiáng)類(lèi)型和弱類(lèi)型的結(jié)合體。為了說(shuō)明這一點(diǎn),我們修改下上例的代碼:
public function billUser(User $user) { $this->biller->bill($user->getId(), $amount); }
在方法參數(shù)中,加入User約定后,就能確保傳入方法的參數(shù)必須是User的實(shí)例化對(duì)象或者是繼承自User的一個(gè)實(shí)例。
兩種類(lèi)型各有優(yōu)劣。強(qiáng)類(lèi)型語(yǔ)言中,編譯器通常提供編譯檢查錯(cuò)誤的功能,它也是非常有用的。方法的輸入和輸出都是明確的。
與此同時(shí),強(qiáng)類(lèi)型的代碼看起來(lái)也是很生硬的。比如Eluquent ORM中提供的動(dòng)態(tài)方法whereEmailOrName就不能象C#那樣明確參數(shù)和返回值的類(lèi)型。這里不討論孰優(yōu)孰劣,我們各取所長(zhǎng),但是,不假思索的死認(rèn)某一種方式肯定會(huì)埋下很多坑。
示例接口就是約定,他不包含具體的代碼實(shí)現(xiàn),而定義了對(duì)象需要實(shí)現(xiàn)的一系列的方法。如果一個(gè)對(duì)象實(shí)現(xiàn)了某個(gè)接口,那么這個(gè)接口的方法肯定都能在這個(gè)實(shí)例對(duì)象中使用。通過(guò)約定固化了某些方法的實(shí)現(xiàn),這種_多態(tài)_就能保證語(yǔ)言的類(lèi)型安全。
什么是多態(tài)?
多態(tài)含義很廣,可以理解為一種實(shí)體的多種形式。在本書(shū)中,我們指代接口的多種實(shí)現(xiàn)方式。例如:UserRepositoryInterface可以有MySQL和Redis兩種存儲(chǔ)實(shí)現(xiàn)方式,但是每一種都是UserRepositoryInter接口的實(shí)現(xiàn)。
為了說(shuō)明強(qiáng)類(lèi)型在接口中的靈活和重要性,我們來(lái)實(shí)現(xiàn)如下一個(gè)酒店預(yù)訂的例子:
interface ProviderInterface { public function getLowestPrice($location); public function book($location); }
當(dāng)用戶預(yù)訂房間是,我們想將此事件記錄到系統(tǒng)中。我們?cè)?b>User類(lèi)中添加如下方法:
class User { public function bookLocation(ProviderInterface $provider, $location) { $amountCharged = $provider->book($location); $this->logBookedLocation($location, $amountCharged); } }
我們限定了參數(shù)$provider的類(lèi)型,User類(lèi)中就能假定book方法是可安全調(diào)用的,這就使得bookLocation有較強(qiáng)的操作性,我們不用關(guān)心酒店是如何實(shí)現(xiàn)房間預(yù)訂這一過(guò)程。下面的代碼就能體現(xiàn)這一特性:
$location = "Hilton, Dallas"; $cheapestProvider = $this->findCheapest($location, array( new PricelineProvider, new OrbitzProvider, )); $user->bookLocation($cheapestProvider, $location);
贊!我們不用關(guān)心那家酒店最便宜,只需要將他傳入User實(shí)例中就能成功預(yù)訂房間。因?yàn)?b>User對(duì)象要求傳入的參數(shù)是繼承自ProviderInterface的對(duì)象,未來(lái)添加更多的酒店提供商,都能使我們的代碼穩(wěn)定的運(yùn)行。
接口和團(tuán)隊(duì)開(kāi)發(fā)忘掉細(xì)節(jié)
記住,接口_不實(shí)現(xiàn)_任何細(xì)節(jié),只是簡(jiǎn)單的定義類(lèi)必須實(shí)現(xiàn)的方法。
當(dāng)團(tuán)隊(duì)構(gòu)建大型應(yīng)用時(shí),不同的模塊進(jìn)程是不同的。比如,有人處理數(shù)據(jù)層,有人處理前端web、控制器層。前端開(kāi)發(fā)項(xiàng)測(cè)試自己的控制器,但是后端人員開(kāi)發(fā)進(jìn)度緩慢。但是,如果我們能約定好接口,后端人員只須遵循接口定義:
interface OrderRepositoryInterface { public function getMostRecent(User $user); }
一旦約定了接口,前端開(kāi)發(fā)人員,在代碼沒(méi)有實(shí)現(xiàn)的情況下,也能測(cè)試自己的控制器!這樣整個(gè)應(yīng)用中就不用擔(dān)心不同模塊的開(kāi)發(fā)進(jìn)度,也不會(huì)影響到正常的測(cè)試用例的編寫(xiě)。更深一點(diǎn)來(lái)說(shuō),這種方法不會(huì)影響到其他組件的開(kāi)發(fā),做到了無(wú)知是福。我們不需要讓我們的類(lèi)必須知道其他類(lèi)是_怎么_實(shí)現(xiàn)的,只需要知道他_能夠_干什么?,F(xiàn)在,我們已經(jīng)定義了接口,那么我們可以繼續(xù)我們控制器代碼的實(shí)現(xiàn)了:
class OrderController { public function __construct(OrderRepositoryInterface $orders) { $this->orders = $orders; } public function getRecent() { $recent = $this->orders->getMostRecent(Auth::user()); return View::make("orders.recent", compact("recent")); } }
前端開(kāi)發(fā)人員可以自己實(shí)現(xiàn)一個(gè)“假”接口,來(lái)測(cè)試應(yīng)用試圖中需要填充的數(shù)據(jù)。
class DummyOrderRepository implements OrderRepositoryInterface { public function getMostRecent(User $user) { return array("Order 1", "Order 2", "Order 3"); } }
接口實(shí)現(xiàn)之后,我們就能將其綁定到容器中,就能在整個(gè)應(yīng)用中使用他了:
App::bind("OrderRepositoryInterface", "DummyOrderRepository");
當(dāng)后端開(kāi)發(fā)人員實(shí)現(xiàn)了他的模塊,比如:RedisOrderRepository。我們?cè)俅瓮ㄟ^(guò)修改綁定將其應(yīng)用到項(xiàng)目之中。
接口大綱
接口在被用來(lái)定義項(xiàng)目“骨架”上是非常有用的。在項(xiàng)目組件設(shè)計(jì)階段可以促進(jìn)團(tuán)隊(duì)間設(shè)計(jì)討論。比如定義BillingNotifierInterface接口,并討論接口相應(yīng)的方法,在敲代碼前就能用接口定義出一套好的API。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/22952.html
摘要:然而,我們需要注意的是僅是軟件設(shè)計(jì)模式依賴注入的一種便利的實(shí)現(xiàn)形式。容器本身不是依賴注入的必要條件,在框架他只是讓其變得更加簡(jiǎn)便。首先,讓我們探索下為什么依賴注入是有益的。繼續(xù)深入讓我們通過(guò)另一個(gè)示例來(lái)加深對(duì)依賴注入的理解。 聲明:本文并非博主原創(chuàng),而是來(lái)自對(duì)《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當(dāng)然也不是原汁原味的翻譯,能保證9...
摘要:實(shí)際上,本原則要求接口必須是粒度明確的。當(dāng)你的代碼不符合接口分離原則時(shí),那也肯定違背了單一責(zé)任原則。接口分離原則本原則是指在實(shí)現(xiàn)類(lèi)中對(duì)于接口中的方法并不強(qiáng)制去實(shí)現(xiàn)使用不到的方法。 聲明:本文并非博主原創(chuàng),而是來(lái)自對(duì)《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當(dāng)然也不是原汁原味的翻譯,能保證90%的原汁性,另外因?yàn)槭抢斫夥g,肯定會(huì)有錯(cuò)誤...
摘要:控制反轉(zhuǎn)容器控制反轉(zhuǎn)使依賴注入變得更加便捷。有瑕疵控制反轉(zhuǎn)容器是實(shí)現(xiàn)的控制翻轉(zhuǎn)容器的一種替代方案。容器的獨(dú)立使用即使沒(méi)有使用框架,我們?nèi)匀豢梢栽陧?xiàng)目中使用安裝組件來(lái)使用的控制反轉(zhuǎn)容器。在沒(méi)有給定任何信息的情況下,容器是無(wú)法實(shí)例化相關(guān)依賴的。 聲明:本文并非博主原創(chuàng),而是來(lái)自對(duì)《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當(dāng)然也不是原汁原味...
摘要:組件擴(kuò)展通常有兩種方法向容器中綁定自己的接口實(shí)現(xiàn)痛過(guò)使用工廠模式實(shí)現(xiàn)的類(lèi)注冊(cè)自己的擴(kuò)展。類(lèi)庫(kù)管理類(lèi)以工廠模式實(shí)現(xiàn),負(fù)責(zé)諸如緩存等驅(qū)動(dòng)的實(shí)例化。閉包須要傳入繼承自和容器的實(shí)例化對(duì)象。當(dāng)完成擴(kuò)展之后要記住中替換成自己的擴(kuò)展名稱。 聲明:本文并非博主原創(chuàng),而是來(lái)自對(duì)《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當(dāng)然也不是原汁原味的翻譯,能保證9...
摘要:在改變存儲(chǔ)系統(tǒng)的情況下,必須對(duì)進(jìn)行修改,違背了開(kāi)放封閉原則。傳統(tǒng)的依賴痛過(guò)倒置就能事代碼變得非常靈活,易于改變 聲明:本文并非博主原創(chuàng),而是來(lái)自對(duì)《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當(dāng)然也不是原汁原味的翻譯,能保證90%的原汁性,另外因?yàn)槭抢斫夥g,肯定會(huì)有錯(cuò)誤的地方,歡迎指正。 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處,謝謝! 依賴反轉(zhuǎn)原則 ...
閱讀 3287·2021-11-08 13:18
閱讀 1420·2021-10-09 09:57
閱讀 1263·2021-09-22 15:33
閱讀 4165·2021-08-17 10:12
閱讀 5175·2021-08-16 11:02
閱讀 2756·2019-08-30 10:56
閱讀 1043·2019-08-29 18:31
閱讀 3318·2019-08-29 16:30