聊聊面向?qū)ο缶幊痰膸讉€(gè)基本原則
來(lái)源:原創(chuàng) 時(shí)間:2017-10-31 瀏覽:0 次進(jìn)行面向目標(biāo)編程,有下面幾個(gè)準(zhǔn)則:
一. 面向籠統(tǒng)準(zhǔn)則
二. 開(kāi)閉準(zhǔn)則
三. 多用組合少用承繼準(zhǔn)則
四. 高內(nèi)聚-低耦合準(zhǔn)則
一. 面向籠統(tǒng)準(zhǔn)則
下面首要先介紹籠統(tǒng)類(lèi)和接口,然后介紹面向籠統(tǒng)編程。
籠統(tǒng)類(lèi)和接口
1.1 籠統(tǒng)類(lèi)
籠統(tǒng)類(lèi)(abstract)具有如下特色:
?
籠統(tǒng)類(lèi)中可以有abstract辦法,也可以有非abstract辦法。
籠統(tǒng)類(lèi)不能運(yùn)用new運(yùn)算符創(chuàng)立目標(biāo)。
如果一個(gè)非籠統(tǒng)類(lèi)是某個(gè)籠統(tǒng)類(lèi)的子類(lèi),那么它有必要重寫(xiě)父類(lèi)的abstract辦法,即在子類(lèi)中將abstract辦法從頭聲明,但有必要去掉abstract修飾符,一起要確保聲明的辦法姓名,回來(lái)類(lèi)型,參數(shù)個(gè)數(shù)和類(lèi)型與父類(lèi)的abstract辦法完全相同。
作為上轉(zhuǎn)型目標(biāo)。雖然籠統(tǒng)類(lèi)不能運(yùn)用new運(yùn)算符創(chuàng)立目標(biāo),但其非abstract子類(lèi)有必要要重寫(xiě)悉數(shù)abstract辦法,這樣一來(lái),就可以讓籠統(tǒng)類(lèi)聲明的目標(biāo)成為其子類(lèi)目標(biāo)的上轉(zhuǎn)型目標(biāo),并調(diào)用子類(lèi)重寫(xiě)的辦法。
例如,下面籠統(tǒng)類(lèi)A中有一個(gè)abstract辦法add(int x,int y);
下列B是A的一個(gè)非abstract子類(lèi),子類(lèi)B在重寫(xiě)父類(lèi)A中的abstract辦法add(int x,int y)時(shí),將其完成為核算參數(shù)x與y的和。
假定b是子類(lèi)B創(chuàng)立的目標(biāo),那么可以讓A類(lèi)聲明的目標(biāo)a成為目標(biāo)b的上轉(zhuǎn)型目標(biāo),即讓a寄存b的引證。上轉(zhuǎn)型目標(biāo)可以調(diào)用子類(lèi)重寫(xiě)的add()辦法,例如:
1.2 接口
如果你也想在IT職業(yè)拿高薪,可以參與我們的訓(xùn)練營(yíng)課程,挑選最適合自己的課程學(xué)習(xí),技能大牛親授,7個(gè)月后,進(jìn)入名企拿高薪。我們的課程內(nèi)容有:Java工程化、高功能及分布式、高功能、淺顯易懂。高架構(gòu)。功能調(diào)優(yōu)、Spring,MyBatis,Netty源碼剖析和大數(shù)據(jù)等多個(gè)知識(shí)點(diǎn)。
接口(interface)具有如下特色:
接口中只可以有public權(quán)限的abstract辦法,不能有非abstract辦法。
接口由類(lèi)去完成,即一個(gè)類(lèi)如果完成一個(gè)接口,那么它有必要重寫(xiě)接口中的abstract辦法,行將abstract辦法從頭聲明,但有必要去掉abstract
修飾符,一起要確保聲明的辦法姓名,回來(lái)類(lèi)型,參數(shù)個(gè)數(shù)和類(lèi)型與接口中的辦法完全相同。
接口回調(diào)。接口回調(diào)是指可以把完成接口的類(lèi)的目標(biāo)的引證賦給該接口聲明的接口變量中,那么該接口變量就可以調(diào)用被類(lèi)完成的接口中的辦法,當(dāng)接口變量調(diào)用被類(lèi)完成的接口中的辦法時(shí),就是告訴相應(yīng)的目標(biāo)調(diào)用接口的辦法,這一進(jìn)程稱(chēng)為目標(biāo)辦法的接口回調(diào)。
例如,下面接口Com中有一個(gè)abstract辦法sub(int x,int y);
ComImp是完成Com接口的類(lèi),ComImp類(lèi)在重寫(xiě)Com接口中的abstract 辦法sub(int x,int y)時(shí),將其完成為核算參數(shù)x與y的差:
可以讓Com接口聲明的接口變量com寄存ComImp類(lèi)的目標(biāo)引證,那么com就可以調(diào)用ComImp類(lèi)完成的接口中的辦法。例如:

面向籠統(tǒng)
所謂面向籠統(tǒng)編程,是指當(dāng)規(guī)劃一個(gè)類(lèi)時(shí),不讓該類(lèi)面向詳細(xì)的類(lèi),而是面向籠統(tǒng)類(lèi)或許接口,即所規(guī)劃類(lèi)中的重要數(shù)據(jù)是籠統(tǒng)類(lèi)或接口聲明的變量,而不是詳細(xì)類(lèi)聲明的變量。
以下通過(guò)一個(gè)簡(jiǎn)略的比方闡明面向籠統(tǒng)編程的思維。
比方,已經(jīng)有了一個(gè)Circle類(lèi),該類(lèi)創(chuàng)立的目標(biāo)circle調(diào)用getArea()辦法可以核算圓的面積,Circle類(lèi)的代碼如下:
現(xiàn)在要規(guī)劃一個(gè)Pillar類(lèi)(柱類(lèi)),該類(lèi)的目標(biāo)調(diào)用getVolume()辦法可以核算柱體體積,Pillar類(lèi)的代碼如下:
上述Pillar類(lèi)中,bottom是用詳細(xì)類(lèi)Circle聲明的變量,如果不觸及用戶(hù)需求的改動(dòng),上面的Pillar類(lèi)的規(guī)劃沒(méi)有任何不當(dāng),但是在某個(gè)時(shí)分,用戶(hù)期望Pillar能創(chuàng)立出底是三角形的柱體。明顯上述Pillar類(lèi)無(wú)法創(chuàng)立出這樣的柱體,即上述規(guī)劃的Pillar類(lèi)不應(yīng)對(duì)用戶(hù)的這種需求。
現(xiàn)在從頭來(lái)規(guī)劃Pillar類(lèi)。首要,注意到柱體核算體積的關(guān)鍵是核算出底面積,一個(gè)柱體在核算底體積時(shí)不應(yīng)該聯(lián)系它的底是怎樣形狀的詳細(xì)圖形,應(yīng)該只關(guān)懷這種圖形是否具有核算面積的辦法。因而,在規(guī)劃Pillar類(lèi)時(shí)不應(yīng)當(dāng)讓它的底是某個(gè)詳細(xì)類(lèi)聲明的變量,一旦這樣做,Pillar類(lèi)就依靠詳細(xì)的類(lèi),缺少?gòu)椥?,難以應(yīng)對(duì)需求的改動(dòng)。
下面將面向籠統(tǒng)從頭規(guī)劃Pillar類(lèi)。首要編寫(xiě)一個(gè)籠統(tǒng)類(lèi)Geometry(或接口),該籠統(tǒng)類(lèi)(接口)中界說(shuō)了一個(gè)籠統(tǒng)的getArea()辦法。
現(xiàn)在Pillar類(lèi)的規(guī)劃者可以面向Geometry 類(lèi)編寫(xiě)代碼,即Pillar類(lèi)應(yīng)當(dāng)把Geometry目標(biāo)作為自己的成員,該成員可以調(diào)用Geometry的子類(lèi)重寫(xiě)的getArea()辦法。這樣一來(lái),Pillar類(lèi)就可以將核算底面積的使命指派給完成Geometry類(lèi)的子類(lèi)的實(shí)例(如果Geometry是一個(gè)接口,Pillar類(lèi)就可以將核算底面積的使命指派給完成Geometry接口的類(lèi)的實(shí)例)。
以下Pillar類(lèi)的規(guī)劃不再依靠詳細(xì)類(lèi),而是面向Geometry類(lèi),即Pillar類(lèi)中的bottom是用籠統(tǒng)類(lèi)Geometry聲明的變量,而不是詳細(xì)類(lèi)聲明的變量。從頭規(guī)劃Pillar類(lèi)的代碼如下:
下面Circle類(lèi)和Rectangle類(lèi)都是Geometry的子類(lèi),二者都有必要重寫(xiě)Geometry 類(lèi)的getArea()辦法來(lái)核算各自的面積。
Circle.java
Rectangle.java
現(xiàn)在,就可以用Pillar類(lèi)創(chuàng)立出具有矩形底或許圓形底的柱體了,如下列Application.java所示:
通過(guò)面向籠統(tǒng)來(lái)規(guī)劃Pillar類(lèi),使得該P(yáng)illar類(lèi)不再依靠詳細(xì)類(lèi),因而每逢體系添加新的Geometry的子類(lèi)時(shí),比方添加一個(gè)Triangle子類(lèi),那么不需求修正Pillar類(lèi)的任何代碼,就可以運(yùn)用Pillar創(chuàng)立出具有三角形底的柱體。
二. 開(kāi)閉準(zhǔn)則
所謂”開(kāi)閉準(zhǔn)則”(Open-Closed Principle)就是讓規(guī)劃對(duì)拓寬敞開(kāi),對(duì)修正封閉。怎樣了解對(duì)拓寬敞開(kāi),對(duì)修正封閉呢?實(shí)際上這句話(huà)的實(shí)質(zhì)是指當(dāng)一個(gè)規(guī)劃中添加新的模塊時(shí),不需求修正現(xiàn)有的模塊。在給出一個(gè)規(guī)劃是,應(yīng)該首要考慮到用戶(hù)需求的改動(dòng),將應(yīng)對(duì)用戶(hù)改動(dòng)的部分規(guī)劃為對(duì)拓寬敞開(kāi),而規(guī)劃的中心部分是通過(guò)精心考慮過(guò)之后斷定下來(lái)的根本結(jié)構(gòu),這部分應(yīng)該是對(duì)修正封閉的,即不能由于用戶(hù)的需求改動(dòng)而再發(fā)生改動(dòng),由于這部分不是用來(lái)應(yīng)對(duì)需求改動(dòng)的。如果規(guī)劃恪守了”開(kāi)-閉準(zhǔn)則”,那么這個(gè)規(guī)劃必定是易保護(hù)的,由于在規(guī)劃中添加新的模塊時(shí),不用去修正規(guī)劃中的中心模塊。比方上面代碼給出的規(guī)劃中有四個(gè)類(lèi),類(lèi)圖如下所示:
該規(guī)劃中的Geometry和Pillar類(lèi)就是體系中隊(duì)修正封閉的部分,而Geometry的子類(lèi)是對(duì)拓寬敞開(kāi)的部分。當(dāng)向體系再添加任何Geometry的子類(lèi)時(shí)(對(duì)拓寬敞開(kāi)),不用修正Pillar類(lèi),就可以運(yùn)用Pillar創(chuàng)立出具有Geometry的心子類(lèi)指定的底的柱體。
一般無(wú)法讓規(guī)劃的每個(gè)部分都恪守”開(kāi)-閉準(zhǔn)則”,甚至不應(yīng)當(dāng)這樣去做,應(yīng)當(dāng)把首要精力會(huì)集在應(yīng)對(duì)規(guī)劃中最有可能因需求改動(dòng)而需求改動(dòng)的當(dāng)?shù)?,然后想辦法運(yùn)用”開(kāi)-閉準(zhǔn)則”。
當(dāng)規(guī)劃某些體系時(shí),常常需求面向籠統(tǒng)來(lái)考慮體系的總體規(guī)劃,不要考慮詳細(xì)類(lèi),這樣就簡(jiǎn)單規(guī)劃出滿(mǎn)意”開(kāi)-閉準(zhǔn)則”的體系,在程序規(guī)劃好后,首要對(duì)abstract類(lèi)的修正封閉,不然,一旦修正abstract類(lèi),比方,為它添加一個(gè)abstract辦法,那么abstract類(lèi)一切的子類(lèi)都需求做出修正;應(yīng)該對(duì)添加abstract類(lèi)的子類(lèi)敞開(kāi),即在程序中再添加子類(lèi)時(shí),不需求修正其他面向籠統(tǒng)類(lèi)而規(guī)劃的重要類(lèi)。
三.多用組合少用承繼準(zhǔn)則
辦法復(fù)用的兩種最常用的技能就是類(lèi)承繼和目標(biāo)組合
承繼和復(fù)用
子類(lèi)承繼父類(lèi)的辦法作為自己的一個(gè)辦法,就好像它們是在子類(lèi)中直接聲明一樣,可以被子類(lèi)中自己聲明的任何實(shí)例辦法調(diào)用。也就是說(shuō),父類(lèi)的辦法可以被子類(lèi)以承繼的辦法復(fù)用。
通過(guò)承繼來(lái)復(fù)用父類(lèi)的辦法的長(zhǎng)處是:
子類(lèi)可以重寫(xiě)父類(lèi)的辦法,即易于修正或許拓寬那些被復(fù)用的辦法。
通過(guò)承繼來(lái)復(fù)用父類(lèi)的辦法的缺陷是:
子類(lèi)從父類(lèi)承繼的辦法在編譯時(shí)就斷定下來(lái)了,所以無(wú)法在運(yùn)轉(zhuǎn)期間改動(dòng)從父類(lèi)承繼的辦法的行為。
子類(lèi)和父類(lèi)的聯(lián)系是強(qiáng)耦合聯(lián)系,也就是說(shuō)當(dāng)父類(lèi)的辦法的行為更改時(shí),必定導(dǎo)致子類(lèi)發(fā)生改動(dòng)。
3.通過(guò)承繼進(jìn)行復(fù)用也稱(chēng)”白盒”復(fù)用,其缺陷是父類(lèi)的內(nèi)部細(xì)節(jié)關(guān)于子類(lèi)而已是可見(jiàn)的。
組合和復(fù)用
一個(gè)類(lèi)的成員變量可以是Java答應(yīng)的任何數(shù)據(jù)類(lèi)型,因而,一個(gè)類(lèi)可以把目標(biāo)當(dāng)作自己的成員變量,如果用這樣的類(lèi)創(chuàng)立目標(biāo),那么該目標(biāo)中就會(huì)有其他目標(biāo),也就是說(shuō),該目標(biāo)將其他目標(biāo)作為自己的組成部分(這就是人們常說(shuō)的Has——A),或許說(shuō)該目標(biāo)是由幾個(gè)目標(biāo)組合而成。
如果一個(gè)目標(biāo)a組合了目標(biāo)b,那么目標(biāo)a就可以托付目標(biāo)b調(diào)用其辦法,即目標(biāo)a以組合的辦法復(fù)用目標(biāo)b的辦法/
通過(guò)組合目標(biāo)來(lái)復(fù)用辦法的長(zhǎng)處是:
通過(guò)組合來(lái)復(fù)用辦法也稱(chēng)”黑盒”復(fù)用,由于當(dāng)時(shí)目標(biāo)只能托付所包括的目標(biāo)調(diào)用其辦法,這樣一來(lái),當(dāng)時(shí)目標(biāo)所包括目標(biāo)辦法的細(xì)節(jié)對(duì)當(dāng)時(shí)目標(biāo)是不行見(jiàn)的。
2.目標(biāo)與所包括目標(biāo)歸于弱耦合聯(lián)系,由于,如果修正當(dāng)時(shí)目標(biāo)所包括目標(biāo)類(lèi)的代碼,不用修正當(dāng)時(shí)目標(biāo)類(lèi)的代碼。
3.當(dāng)時(shí)目標(biāo)可以在運(yùn)轉(zhuǎn)時(shí)動(dòng)態(tài)指定所包括的目標(biāo),例如,假定Com是以惡搞接口,該接口中有一個(gè)computer()辦法,那么下列Computer類(lèi)的目標(biāo)可以在運(yùn)轉(zhuǎn)時(shí)動(dòng)態(tài)指定所包括的目標(biāo),即運(yùn)轉(zhuǎn)期間,Computer類(lèi)的實(shí)例可調(diào)用setCom(Com com)辦法將其間的com變量寄存任何完成Com接口目標(biāo)的引證。
通過(guò)組合目標(biāo)來(lái)復(fù)用辦法的缺陷是:
1.簡(jiǎn)單導(dǎo)致體系中的目標(biāo)過(guò)多。
2.為了可以組合多個(gè)目標(biāo),有必要細(xì)心的對(duì)接口進(jìn)行界說(shuō)
多用組合,少用承繼
之所以發(fā)起多用組合,少用承繼,是由于在許多規(guī)劃中,人們期望體系的類(lèi)之間盡量是低耦合聯(lián)系,而不期望是強(qiáng)耦合聯(lián)系。即在許多情況下需求避開(kāi)承繼的缺陷,而需求組合的長(zhǎng)處。怎樣樣合理地運(yùn)用組合,而不是運(yùn)用承繼來(lái)取得辦法的復(fù)用需求通過(guò)必定時(shí)刻的認(rèn)真思考,學(xué)習(xí)和編程實(shí)踐才干悟出其間的道理。
四. 高內(nèi)聚-低耦合準(zhǔn)則
如果類(lèi)中的辦法是一組相關(guān)的行為,則稱(chēng)該類(lèi)是高內(nèi)聚的,反之稱(chēng)為低內(nèi)聚的。搞內(nèi)聚便于類(lèi)的保護(hù),而低內(nèi)聚不利于類(lèi)的保護(hù)。