




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
對(duì)修改是關(guān)閉的,意味著當(dāng)對(duì)軟件實(shí)體進(jìn)行擴(kuò)展的時(shí)候,不需要改動(dòng)當(dāng)前的軟件實(shí)體;不需要修改代碼;對(duì)于已經(jīng)完成的類文件不需要重新編輯;對(duì)于已經(jīng)編譯打包好的模塊,不需要再重新編譯。假設(shè)我們需要設(shè)計(jì)一個(gè)可以通過(guò)按鈕撥號(hào)的,對(duì)象是按鈕和撥號(hào)器。那么簡(jiǎn)單的設(shè)代代1234publicclassButtonpublicfinalstaticintSEND_BUTTON=-private556789privatepublicButton(inttoken,Dialer{this.token=token;this.dialer=}publicvoid{switch(token){case0:casecasecasecasecasecasecasecasecasecaseSEND_BUTTON:thrownew}}button}代代123456789publicclassDialerpublicvoidenterDigit(int{System.out.println("enterdigit:"+publicvoid{;}press()用撥號(hào)器Dailer的相關(guān)方法。這個(gè)代碼能夠正常運(yùn)行,完成需求,設(shè)計(jì)似乎也沒(méi)什么問(wèn)這樣的代碼我們司空見(jiàn)慣,但是它的設(shè)計(jì)了開(kāi)閉原則:當(dāng)我們想要增加按鈕類型的時(shí)候,比如,當(dāng)我們需要按鈕支持星號(hào)(*)和井號(hào)(#)的時(shí)候,須修改Btton當(dāng)我要用按鈕一個(gè)鎖而撥號(hào)時(shí)候?yàn)榘绰?lián)了器,所以依然要修改Bttontton似乎對(duì)Button類做任何的功能擴(kuò)展,都要修改Button類,這顯然了開(kāi)閉原則:對(duì)功開(kāi)閉原則的是,這個(gè)Btton類非常僵硬,當(dāng)我們想要進(jìn)行任何需求變更的時(shí)候,都必須要修改代碼。同時(shí)我們需要注意,大段的s/e語(yǔ)句是非常脆弱的,當(dāng)需要新的類型候,非常地在代碼到合位置不可能現(xiàn)bu。一當(dāng)我們?cè)诖a中看到else或者switch/case關(guān)鍵字的時(shí)候,基本可以判斷開(kāi)閉原則了。而且,這個(gè)Button類也是難以復(fù)用的,Button類強(qiáng)耦合了一個(gè)Dailer類,在脆弱的switch/caseDailerButton合在一起,當(dāng)復(fù)用這個(gè)Button類的時(shí)候,不管我需不需要一個(gè)Send按鈕,Button所以,這樣的設(shè)計(jì)不要說(shuō)不修改代碼就能實(shí)現(xiàn)功能擴(kuò)展,即使我們想修改代碼進(jìn)行功能擴(kuò)展,里面也很脆弱,稍不留心就掉到坑里了。這個(gè)時(shí)候你再回頭審視Btton感覺(jué)代碼腐壞道,讓你手代碼需求,是頭疼很多設(shè)計(jì)開(kāi)始看并沒(méi)有什么問(wèn)題,如果軟件開(kāi)發(fā)出來(lái)也不需要修改,也許怎么設(shè)計(jì)都可以,但是當(dāng)需求變更來(lái)的時(shí)候,就會(huì)發(fā)現(xiàn)各種僵硬、脆弱。所以設(shè)計(jì)的優(yōu)劣需要放入需求變更的場(chǎng)景中。當(dāng)需求變更時(shí)發(fā)現(xiàn)當(dāng)前設(shè)計(jì)的腐壞,就要及時(shí)進(jìn)行重構(gòu),保持設(shè)計(jì)的強(qiáng)壯和代碼的干凈。ButtonDailerButtonServer,ButtonButtonServerDailerButtonServer當(dāng)Button按下的時(shí)候,就調(diào)用ButtonServer的buttonPressed方法,事實(shí)上是調(diào)用Dailer實(shí)現(xiàn)的buttonPressed方法,這樣既完成了Button按下的時(shí)候執(zhí)行Dailer方法的需求,又不會(huì)使Button依賴Dailer。Button可以擴(kuò)展復(fù)用到其他需要使用Button的場(chǎng)景,任何實(shí)現(xiàn)ButtonServer的類,比如鎖,都可以使用Button,而不需要對(duì)Button而且Button也不需要switch/case代碼段去判斷當(dāng)前按鈕類型,只需要將按鈕類型token傳遞給ButtonServer就可以了,這樣增加新的按鈕類型的時(shí)候就不需要修改Button代碼 在我們這個(gè)場(chǎng)景中,程序就是Button,策略就是需要用Button控制的目標(biāo)設(shè)備,撥號(hào)器、鎖等等,ButtonServer就是策略接口。通過(guò)使用策略模式,我們使ButtonButton符合開(kāi)閉原則了,但是Dailer又不符合開(kāi)閉原則了,因?yàn)镈ailer要實(shí)現(xiàn)ButtonServertokenenterDigitdailif/else或者switch/case,不符合開(kāi)閉原則。這種情況可以使用適配器模式ar類直接實(shí)現(xiàn)BttonSever接口,而是增加兩個(gè)適配器tBrAdeptrBttrAdtrBttonrvr接口,在適配器的buttd方法中調(diào)用ar的ttdailaerar類實(shí)現(xiàn)開(kāi)閉原則。在我們這個(gè)場(chǎng)景中,Button需要調(diào)用的接口是buttonPressed,和Dailer的方法不匹配,如何在不修改Dailer代碼的前提下,使Button能夠調(diào)用Dailer代碼?就是靠適配器,DigitButtonDailerAdepterSendButtonDailerAdepter接口,使Button能夠調(diào)用自己,并在自己的buttonPressed方法中調(diào)用Dailer的方法,適配了Dailer。通過(guò)策略模式和適配器模式,我們使Button和Dailer都符合了開(kāi)閉原則。但是如果要求這里,ButtonServer被改名為ButtonListener,表示這是一個(gè)者接口,其實(shí)這個(gè)改名不重要,僅僅是為了便于識(shí)別。因?yàn)榻涌诜椒╞uttonPressed不變,ButtonListener和ButtonServer本質(zhì)上是一樣的。重要的是在Button類里增加了成員變量List和成員方法addListener。通過(guò)addListener,我們可以添加多個(gè)需要觀察按鈕按下的者實(shí)現(xiàn),當(dāng)按鈕需要控制新設(shè)備的時(shí)候,只需要將實(shí)現(xiàn)了ButtonListener的設(shè)備實(shí)現(xiàn)添加到Button的ListButton代碼publicclassButtonprivateList<ButtonListener>publicButton()this.listeners=new 7publicvoidaddListener(ButtonListenerlistener)assertlistener!= publicvoidpress()for(ButtonListenerlistener:listeners) 18代12代123456789publicclassPhoneprivateprivateButton[]digitButtons;privateButton publicPhone()dialer=newDialer();digitButtons=newButton[10];for(inti=0;i<digitButtons.length;{digitButtons[i]=newButton();finalintdigit=i;digitButtons[i].addListener(newButtonListener(){publicvoidbuttonPressed(){}}sendButton=newButton();sendButton.addListener(newButtonListener(){publicvoid{}}publicstaticvoidmain(String[]{Phonephone=newPhone();}}在我們這個(gè)場(chǎng)景中,Button是被觀察者,目標(biāo)設(shè)備撥號(hào)器、鎖等是觀察者。被觀察者和觀察者通過(guò)Listener接口解耦合,觀察者(的適配器)通過(guò)調(diào)用被觀察者的addListener方法將自己添加到觀察列表,當(dāng)觀察行為發(fā)生時(shí),被觀察者會(huì)逐個(gè)遍歷ListenerList,通知觀察者。如果業(yè)務(wù)要求按下按鈕的時(shí)候,除了控制設(shè)備,按鈕本身還需要執(zhí)行一些操作,完成一些成員變量的狀態(tài)更改,不同按鈕類型進(jìn)行的操作和記錄狀態(tài)各不相同。按照當(dāng)前設(shè)計(jì)可能又要在Btton的press方法中增加s/eButtononPressSendButton法。ButtononPresspressonPress代代12345678voidpublicvoid{for(ButtonListenerlistener:{}}在我們這個(gè)例子中,presspress方法除了調(diào)用抽象方法onPres,還執(zhí)行通知者列表的操作,這些抽象方法和具體操作共同構(gòu)成了模板。而在子類中實(shí)現(xiàn)這個(gè)抽象方法,在這個(gè)方法中修改狀態(tài),完成自己類型特有的操作,這就是模板方法通過(guò)模板方法模式,每個(gè)子類可以定義自己在press執(zhí)行時(shí)的狀態(tài)操作,無(wú)需修改實(shí)現(xiàn)開(kāi)閉原則的關(guān)鍵是抽象。當(dāng)一個(gè)模塊依賴的是一個(gè)抽象接,就可以隨意對(duì)這抽象接口進(jìn)行擴(kuò)展,這個(gè)時(shí)候,不需要對(duì)現(xiàn)有代碼進(jìn)行任何修改,利用接口的多態(tài)性,通過(guò)增加一個(gè)新實(shí)現(xiàn)該接口的實(shí)現(xiàn)類,就能完成需求變更。不同場(chǎng)景進(jìn)行擴(kuò)展的方式是不同的,這時(shí)候就會(huì)產(chǎn)生不同的設(shè)計(jì)模式,大部分的設(shè)計(jì)模式都是用來(lái)解決擴(kuò)展的靈活性問(wèn)題的。開(kāi)閉原則可以說(shuō)是軟件設(shè)計(jì)原則的原則,是軟件設(shè)計(jì)的原則,其他的設(shè)計(jì)原則更偏向技術(shù)性,具有技術(shù)性的指導(dǎo)意義,而開(kāi)閉原則是方向性的,在軟件設(shè)計(jì)的過(guò)程中,應(yīng)該時(shí)刻以開(kāi)閉原則指導(dǎo)、審視自己的設(shè)計(jì):當(dāng)需求變更的時(shí)候,現(xiàn)在的設(shè)計(jì)能否不修改代碼就可以實(shí)我在觀察者模式小節(jié)展示的Phone代碼示例中,并沒(méi)有顯式定義DigitButtonDailerAdepterSendButtonDailerAdepter 售賣。頁(yè)面已增加防盜追蹤,將依 其上一 10|軟件設(shè)計(jì)的目的:糟糕的程序員比優(yōu)秀的程序員差在哪里下一 12|軟件設(shè)計(jì)的依賴倒置原則:如何不依賴代碼卻可以復(fù)用它的功能言言pspps看起來(lái)復(fù)雜的設(shè)計(jì)模式就是用來(lái)解決問(wèn)題的,正確使用設(shè)計(jì)模式,看起來(lái)復(fù)雜了,91 2RoypublicclassButtonprivateButtonServerserver;privateinttoken;…1Jonathan1 1RoypublicclassCodeCase{privateD
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 書(shū)法代售合同范本
- 門(mén)診研究課題申報(bào)書(shū)
- 公司收購(gòu)股權(quán)合同范本
- 廠場(chǎng)租賃合同范本
- 職業(yè) 課題申報(bào)書(shū)
- 醫(yī)療會(huì)議服務(wù)合同范本
- 員工入職合同范本文本
- 【復(fù)習(xí)大串講】【中職專用】高二語(yǔ)文上學(xué)期期末期末綜合測(cè)試題(二)(職業(yè)模塊)(解析版)
- 行動(dòng)導(dǎo)向課題申報(bào)書(shū)
- 三方租賃合同范本
- 皮膚性病學(xué)課件:濕疹皮炎
- 綠化養(yǎng)護(hù)重點(diǎn)難點(diǎn)分析及解決措施
- 醫(yī)療垃圾管理及手衛(wèi)生培訓(xùn)PPT課件
- 一體化學(xué)工服務(wù)平臺(tái)、人事管理系統(tǒng)、科研管理系統(tǒng)建設(shè)方案
- 市場(chǎng)營(yíng)銷學(xué)課后習(xí)題與答案
- 嚇數(shù)基礎(chǔ)知識(shí)共20
- 常暗之廂(7規(guī)則-簡(jiǎn)體修正)
- 10kV變電所設(shè)備檢修內(nèi)容與周期表
- 井控系統(tǒng)操作維護(hù)與保養(yǎng)規(guī)程
- 電子產(chǎn)品高可靠性裝聯(lián)工藝下
- 越南北部工業(yè)區(qū)資料(1060707)
評(píng)論
0/150
提交評(píng)論