![設(shè)計(jì)模式筆試面試常見問題_第1頁](http://file4.renrendoc.com/view/89c080518c6074ed6be44d64f6131b2f/89c080518c6074ed6be44d64f6131b2f1.gif)
![設(shè)計(jì)模式筆試面試常見問題_第2頁](http://file4.renrendoc.com/view/89c080518c6074ed6be44d64f6131b2f/89c080518c6074ed6be44d64f6131b2f2.gif)
![設(shè)計(jì)模式筆試面試常見問題_第3頁](http://file4.renrendoc.com/view/89c080518c6074ed6be44d64f6131b2f/89c080518c6074ed6be44d64f6131b2f3.gif)
![設(shè)計(jì)模式筆試面試常見問題_第4頁](http://file4.renrendoc.com/view/89c080518c6074ed6be44d64f6131b2f/89c080518c6074ed6be44d64f6131b2f4.gif)
![設(shè)計(jì)模式筆試面試常見問題_第5頁](http://file4.renrendoc.com/view/89c080518c6074ed6be44d64f6131b2f/89c080518c6074ed6be44d64f6131b2f5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
設(shè)計(jì)模式有哪幾種單例模式中如何實(shí)現(xiàn)并發(fā)的懶漢模式最簡(jiǎn)單的實(shí)現(xiàn)首先,能夠想到的最簡(jiǎn)單的實(shí)現(xiàn)是,把類的構(gòu)造函數(shù)寫成private的,從而保證別的類不能實(shí)例化此類,然后在類中提供一個(gè)靜態(tài)的實(shí)例并能夠返回給使用者。這樣,使用者就可以通過這個(gè)引用使用到這個(gè)類的實(shí)例了。publicclassSingletonClass{privatestaticfinalSingletonClassinstanee=newSingletonClass();publicstaticSingletonClassgetInstance(){returninstanee;}privateSingletonClass(){}}如上例,外部使用者如果需要使用SingletonClass的實(shí)例,只能通過getInstance()方法,并且它的構(gòu)造方法是private的,這樣就保證了只能有一個(gè)對(duì)象存在。性能優(yōu)化 lazyloaded上面的代碼雖然簡(jiǎn)單,但是有一個(gè)問題一一無論這個(gè)類是否被使用,都會(huì)創(chuàng)建一個(gè)instance對(duì)象。如果這個(gè)創(chuàng)建過程很耗時(shí),比如需要連接10000次數(shù)據(jù)庫(夸張了…:-)),并且這個(gè)類還并不一定會(huì)被使用,那么這個(gè)創(chuàng)建過程就是無用的。怎么辦呢?為了解決這個(gè)問題,我們想到了新的解決方案:publicclassSingletonClass{privatestaticSingletonClassinstanee=null;publicstaticSingletonClassgetInstance(){if(instanee==null){instanee=newSingletonClass();}returninstanee;}privateSingletonClass(){}}代碼的變化有兩處首先,把instance初始化為null,直到第一次使用的時(shí)候通過判斷是否為null來創(chuàng)建對(duì)象。因?yàn)閯?chuàng)建過程不在聲明處,所以那個(gè)final的修飾必須去掉。我們來想象一下這個(gè)過程。要使用SingletonClass,調(diào)用getinstance()方法。第一次的時(shí)候發(fā)現(xiàn)instance是null,然后就新建一個(gè)對(duì)象,返回出去;第二次再使用的時(shí)候,因?yàn)檫@個(gè)instance是static的,所以已經(jīng)不是null了,因此不會(huì)再創(chuàng)建對(duì)象,直接將其返回。這個(gè)過程就成為lazyloaded,也就是遲加載 直到使用的時(shí)候才進(jìn)行加載。同步上面的代碼很清楚,也很簡(jiǎn)單。然而就像那句名言:“80%的錯(cuò)誤都是由20%代碼優(yōu)化引起的”。單線程下,這段代碼沒有什么問題,可是如果是多線程,麻煩就來了。我們來分析一下:線程A希望使用SingletonClass,調(diào)用getInstance()方法。因?yàn)槭堑谝淮握{(diào)用,A就發(fā)現(xiàn)instance是null的,于是它開始創(chuàng)建實(shí)例,就在這個(gè)時(shí)候,CPU發(fā)生時(shí)間片切換,線程B開始執(zhí)行,它要使用SingletonClass,調(diào)用getInstance()方法,同樣檢測(cè)到instance是null注意,這是在A檢測(cè)完之后切換的,也就是說A并沒有來得及創(chuàng)建對(duì)象——因此B開始創(chuàng)建。B創(chuàng)建完成后,切換到A繼續(xù)執(zhí)行,因?yàn)樗呀?jīng)檢測(cè)完了,所以A不會(huì)再檢測(cè)一遍,它會(huì)直接創(chuàng)建對(duì)象。這樣,線程A和B各自擁有一個(gè)SingletonClass的對(duì)象 單例失??!解決的方法也很簡(jiǎn)單,那就是加鎖:publicclassSingletonClass{privatestaticSingletonClassinstanee=null;publicsynchronizedstaticSingletonClassgetInstance(){if(instanee==null){instanee=newSingletonClass();}returninstanee;}privateSingletonClass(){}}是要getInstance()加上同步鎖,一個(gè)線程必須等待另外一個(gè)線程創(chuàng)建完成后才能使用這個(gè)方法,這就保證了單例的唯一性。又是性能上面的代碼又是很清楚很簡(jiǎn)單的,然而,簡(jiǎn)單的東西往往不夠理想。這段代碼毫無疑問存在性能的問題 synchronized修飾的同步塊可是要比一般的代碼段慢上幾倍的!如果存在很多次getInstance()的調(diào)用,那性能問題就不得不考慮了!讓我們來分析一下,究竟是整個(gè)方法都必須加鎖,還是僅僅其中某一句加鎖就足夠了?我們?yōu)槭裁匆渔i呢?分析一下出現(xiàn)lazyloaded的那種情形的原因。原因就是檢測(cè)null的操作和創(chuàng)建對(duì)象的操作分離了。如果這兩個(gè)操作能夠原子地進(jìn)行,那么單例就已經(jīng)保證了。于是,我們開始修改代碼:publicclassSingletonClass{privatestaticSingletonClassinstanee=null;publicstaticSingletonClassgetInstance(){synchronized(SingletonClass.class){if(instanee==null){instanee=newSingletonClass();}}returninstanee;}privateSingletonClass(){}}首先去掉getinstance()的同步操作,然后把同步鎖加載if語句上。但是這樣的修改起不到任何作用:因?yàn)槊看握{(diào)用getInstance()的時(shí)候必然要同步,性能問題還是存在。如果 如果我們事先判斷一下是不是為null再去同步呢?publicclassSingletonClass{privatestaticSingletonClassinstanee=null;publicstaticSingletonClassgetInstance(){if(instanee==null){synchronized(SingletonClass.class){if(instanee==null){instanee=newSingletonClass();}}}returninstanee;privateSingletonClass(){}}還有問題嗎?首先判斷instance是不是為null,如果為null,加鎖初始化;如果不為null,直接返回instance。這就是double-checkedlocking設(shè)計(jì)實(shí)現(xiàn)單例模式。到此為止,一切都很完美。我們用一種很聰明的方式實(shí)現(xiàn)了單例模式責(zé)任鏈問題A:實(shí)行一個(gè)過濾功能,過濾一段文字首先獲取用戶輸入的一段文字:Stringmsg="大家好:),<script>,敏感,被就業(yè),網(wǎng)絡(luò)授課沒感覺,因?yàn)榭床灰姶蠹一飪?;那么我們寫一個(gè)filterMethod(){};使用最簡(jiǎn)單的replace方法替換文中的敏感詞問題B:如果想用面向?qū)ο蟮姆椒ㄈ?shí)現(xiàn)呢?創(chuàng)建一個(gè)類MsgProcessor專門用來處理用戶輸入的文字,該類用一個(gè)屬性message(用戶輸入文字),生成set/get方法,(為什么要通過set/get方法去訪問屬性,而不直接訪問該屬性???為了保護(hù)該屬性,不讓用戶直接訪問修改,如果是你的存折,你可以在set/get方法中加入權(quán)限判斷,避免讓用戶直接訪問操作;如果讓該屬性只能夠看,不能夠修改,則直接刪除set方法即可)一個(gè)方法process()(處理文字) 每次只需要將MsgProcessormp=newMsgProcessor();mp.setMsg(msg);cess();問題C:如果我們有多個(gè)過濾器,那么如何設(shè)計(jì)會(huì)更加方便以后繼續(xù)添加??首先我們寫一個(gè)接口Filter,它有一個(gè)doFilter方法,publicinterfaceFilter{StringdoFilter(Stringstr); }制作接口相當(dāng)于給所有開發(fā)人員制定了規(guī)范,然后我們寫的每一個(gè)過濾器類都要實(shí)現(xiàn)該接口,由于有多個(gè)過濾器類,所以我們建立一個(gè)過濾器類的集合類FilterChain,它需要實(shí)現(xiàn)Filter接口,同時(shí)要擁有過濾器集合變量publicclassFilterChainimplementsFilter{用集合的好處當(dāng)有新的過濾器或者過濾器集合類要添加進(jìn)來,會(huì)更加方便List<Filter>filters=newArrayList<Filter>();publicFilterChainaddFilter(Filterf){//能夠?qū)⒆宇惿傻膶?duì)象賦值給父類,但是不能將父類生成的對(duì)象賦值給子類
//并且能夠?qū)?shí)現(xiàn)接口的類的對(duì)象賦值給父類接口,同上一樣this.filters?add(f);returnthis;//返回this,也就是返回FilterChain本身對(duì)象}publicStringdoFilter(Stringstr){Stringr=str;for(Filterf:filters){r=f.doFilter(r);} //逐個(gè)調(diào)用過濾器的dofilter方法returnr;}那么單個(gè)的過濾器例如HTMLFilter,只需要執(zhí)行自己的操作publicclassHTMLFilterimplementsFilter{@OverridepublicStringdoFilter(Stringstr){//processthehtmltag<>Stringr=str.replace('<','[')?replace('>',']');returnr;}}通常我們不希望這樣添加Filter[]filters={newHTMLFilter(),newSesitiveFilter(),newFaceFilter()};因?yàn)檫@樣會(huì)使得每次只要添加新的過濾器,都要修改這個(gè)類,所以我們直接使用集合。那么在main函數(shù)中,由于addFilter返回的this,所以可以連寫FilterChainfc=newFilterChain();fc.addFilter(newHTMLFilter())?addFilter(newSesitiveFilter())?addFilter(newFaceFilter());問題D:如何繼續(xù)優(yōu)化該段代碼呢?我們希望msgProcess的process方法執(zhí)行何功能?也就是需要在MsgProcessor類中加入成員變量FilterChainfc;publicStringprocess(){returnfc.doFilter(msg);}那么要想用MsgProcessor類的對(duì)象調(diào)用process方法,就必須要在MsgProcessor類中生成fc的set/get方法;Stringresult=cess();問題E:回顧流程1、 封裝用戶輸入的文本,成員變量msg(文本),Fc(過濾器對(duì)象)成員方法process(處理文本)2、 建立過濾器接口,制定規(guī)范3、 創(chuàng)建過濾器集合類,每增加一個(gè)過濾器,都添加到集合中去,完成父類方法,循環(huán)調(diào)用集合中所有過濾器的方法4、 如果新加一個(gè)過濾器,完成好類實(shí)現(xiàn)之后,只需要在main方法中加入進(jìn)去即可,方便調(diào)節(jié)過濾器的執(zhí)行順序問題F:以上我們只做了從客戶端發(fā)送到服務(wù)器端的文本處理,如果我們也希望同時(shí)處理服務(wù)器端到客戶端的文本,那么該如何做?該實(shí)現(xiàn)的思想與struets中攔截器的實(shí)現(xiàn)思想一致理解堆棧的思想,先進(jìn)后出;也就是說,當(dāng)我們通過服務(wù)器端的攔截器1,2,3,4處理完文本后,再返回到客戶端之前,仍然需要進(jìn)行攔截器的處理,只不過執(zhí)行順序是攔截器4,3,2,1。首先接口Filter,我們需要修改其doFilTeR方法voiddoFiITer(RequesTrequesT,Responseresponse,FilTerChainchain);在main函數(shù)中,我們創(chuàng)建模擬的RequesT,Response類Stringmsg="大家好:),<scripT>,敏感,被就業(yè),網(wǎng)絡(luò)授課沒感覺,因?yàn)榭床灰姶蠹一飪?;RequesTrequesT=newRequesT();requesT.seTRequesTSTr(msg);Responseresponse=newResponse();response.seTResponseSTr("response");然后通過FilTerChain進(jìn)行處理,只不過需要將doFilTer方法改寫@OverridepublicvoiddoFilter(Requestrequest,Responseresponse,FilterChainchain){//如果已經(jīng)達(dá)到過濾器集合的數(shù)目,就返回if(index==filters?size())return;//獲取當(dāng)前過濾器Filterf=filters?get(index);//加1,使下次調(diào)用下一個(gè)過濾器index++;f?doFilter(request,response,chain);}那么同時(shí)也要改寫HTMLFilter類,假設(shè)該類是第一個(gè)添加到集合類中@OverridepublicvoiddoFilter(Requestrequest,Responseresponse,FilterChainchain){//processthehtmltag<>request?requestStr=request?requestStr.replace('<','[').replace('>',']')+"——HTMLFilter()";chain.doFilter(request,response,chain);response.responseStr+="——HTMLFilter()";}那么執(zhí)行第一步,處理request傳來的字符串,執(zhí)行到第二步時(shí),執(zhí)行dofilter方法重新調(diào)用到filterChain的dofilter方法,但這時(shí)index++,會(huì)調(diào)用第二個(gè)過濾器類的方法。依次循環(huán),直到if(index==filters?size())return;就會(huì)執(zhí)行下一句第三步,也就是處理response工產(chǎn)系列老張手拿AK47,嘴里叼著雪茄,開著奔馳車,一路哼著歌奔向東北一個(gè)人擁有這么多東西,相當(dāng)于一個(gè)工廠,于是我們幫他設(shè)計(jì)一個(gè)抽象工廠類,由于是具體的我們給它設(shè)計(jì)成抽象類,而非接口publicabstractclassAbstractFactory{publicabstractVehiclecreateVehicle();publicabstractWeaponcreateWeapon();publicabstractFoodcreateFood();}當(dāng)然Vehicle、Weapon、Food這些肯定也會(huì)弄成抽象類。publicabstractclassFood{publicabstractvoidprintName();}publicabstractclassVehicle{publicabstractvoidrun();}publicabstractclassWeapon{publicabstractvoidshoot();}也就由具體的類去繼承并實(shí)現(xiàn)其抽象方法例如:publicclassCarextendsVehicle{publicvoidrun(){System,out.println(”冒著煙奔跑中car ");}}publicclassAK47extendsWeapon{publicvoidshoot(){System,out.println("噠噠噠???");}}publicclassAppleextendsFood{publicvoidprintName(){System,out?println("apple");}}好的,那么我們?cè)O(shè)計(jì)一個(gè)默認(rèn)的工廠publicclassDefaultFactoryextendsAbstractFactory{@Overridep
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 教育培訓(xùn)機(jī)構(gòu)評(píng)估居間合同
- 紡織品交易居間合同協(xié)議書
- 2025年度辦公室日常保潔與節(jié)能照明設(shè)備供應(yīng)服務(wù)合同
- 廣告投放數(shù)據(jù)分析合同
- 產(chǎn)品包裝設(shè)計(jì)技術(shù)指南
- 安全生產(chǎn)托管協(xié)議合同
- 工礦企業(yè)產(chǎn)品購銷合同
- 廚房承包協(xié)議集錦
- 農(nóng)業(yè)質(zhì)量標(biāo)準(zhǔn)制定指南
- 能源行業(yè)能源供應(yīng)鏈優(yōu)化與智能倉儲(chǔ)管理
- 譯林版八年級(jí)英語下冊(cè)英語單詞(帶默寫版)
- 高中數(shù)學(xué)平面幾何強(qiáng)化訓(xùn)練(解析版)
- 《祛痘產(chǎn)品祛痘產(chǎn)品》課件
- 江蘇省南京鼓樓區(qū)2024年中考聯(lián)考英語試題含答案
- 人輪狀病毒感染
- 兒科護(hù)理學(xué)試題及答案解析-神經(jīng)系統(tǒng)疾病患兒的護(hù)理(二)
- 《石油產(chǎn)品分析》課件-車用汽油
- 《你為什么不開花》兒童故事繪本
- 15篇文章包含英語四級(jí)所有詞匯
- 王陽明心學(xué)完整版本
- 四年級(jí)上冊(cè)豎式計(jì)算300題及答案
評(píng)論
0/150
提交評(píng)論