六大設(shè)計(jì)原則_第1頁(yè)
六大設(shè)計(jì)原則_第2頁(yè)
六大設(shè)計(jì)原則_第3頁(yè)
六大設(shè)計(jì)原則_第4頁(yè)
六大設(shè)計(jì)原則_第5頁(yè)
已閱讀5頁(yè),還剩61頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

六大設(shè)計(jì)原則——設(shè)計(jì)模式之禪秦小波Contents單一職責(zé)原則1里氏替換原則2依賴倒置原則3接口隔離原則4迪米特法則5開(kāi)閉原則6單一職責(zé)原則單一職責(zé)原則(SingleResponsibilityPrinciple,SRP):Thereshouldneverbemorethanonereasonforaclasstochange.應(yīng)該有且僅有一個(gè)原因引起類的變更

基于角色的訪問(wèn)控制:用戶管理修改用戶信息信息增加機(jī)構(gòu)(一個(gè)人屬于多個(gè)機(jī)構(gòu))增加角色設(shè)計(jì)問(wèn)題用戶的屬性和行為沒(méi)有分開(kāi)收集和反饋用戶信息完成用戶信息的維護(hù)和變更為什么要把一個(gè)接口拆分成兩個(gè)呢?——單一職責(zé)原則在實(shí)際的使用中,更傾向于使用兩個(gè)不用的類或接口,如右圖所示:?jiǎn)我宦氊?zé)原則舉例單一職責(zé)原則Iphone這個(gè)接口有兩個(gè)職責(zé):一個(gè)是協(xié)議管理,一個(gè)是數(shù)據(jù)傳送;其中diag()和huangup()兩個(gè)方法實(shí)現(xiàn)的是協(xié)議管理,撥號(hào)接通和關(guān)閉;Chat()和answer()是數(shù)據(jù)的傳送,把說(shuō)的話轉(zhuǎn)換成模擬信號(hào)或者是數(shù)字信號(hào)傳遞到對(duì)方,然后再把對(duì)方傳遞的信號(hào)轉(zhuǎn)換。問(wèn)題:1.兩個(gè)職責(zé)都能引起類的變化嗎?2.兩個(gè)變化會(huì)相互影響嗎?這個(gè)Iphone接口包含了兩個(gè)職責(zé),而且這兩個(gè)職責(zé)的變化不相互影響,那就考慮拆開(kāi)成兩個(gè)接口。單一職責(zé)原則單一職責(zé)原則的優(yōu)點(diǎn):類的復(fù)雜性降低:實(shí)現(xiàn)什么職責(zé)都有清晰明確的定義;可讀性提高:復(fù)雜性降低,可讀性就會(huì)提高;可維護(hù)性提高變更引起的風(fēng)險(xiǎn)降低:變更是必不可少的,接口的單一職責(zé)做好的話,一個(gè)接口修改只對(duì)相應(yīng)的類有影響,與其他接口無(wú)影響,這對(duì)項(xiàng)目有非常大的幫助對(duì)于接口,設(shè)計(jì)時(shí)要做到單一,但是對(duì)于實(shí)現(xiàn)類就要多方考慮了,硬套單一職責(zé)原則會(huì)引起類的劇增,給維護(hù)帶來(lái)非常多的麻煩,過(guò)分的細(xì)分類也人為的制造系統(tǒng)的負(fù)擔(dān)。繼承機(jī)制的優(yōu)缺點(diǎn)在面向?qū)ο蟮恼Z(yǔ)言中,繼承是必不可少的、非常優(yōu)秀的語(yǔ)言機(jī)制,它有如下優(yōu)點(diǎn):代碼共享,減少創(chuàng)建類的工作量,每個(gè)子類都擁有父類的方法和屬性;提高代碼的重用性;子類可以形似父類,但又異于父類;提高代碼的可擴(kuò)展性;提高產(chǎn)品或項(xiàng)目的開(kāi)放性。自然界的所有事物都是有點(diǎn)和缺點(diǎn)并存的,繼承的缺點(diǎn)如下:繼承是侵入性的。只要繼承,就必須擁有父類的所有屬性和方法;降低了代碼的靈活性。子類必須擁有父類的屬性和方法,讓子類自由的世界中多了些約束;增強(qiáng)了耦合性。當(dāng)父類的常量、變量和方法被修改時(shí),必須要考慮子類的修改,而且在缺乏規(guī)范的環(huán)境下,這種修改可能帶來(lái)非常糟糕的結(jié)果——大片的代碼需要重構(gòu)。繼承機(jī)制的優(yōu)缺點(diǎn)里氏替換原則問(wèn)題:怎樣才能讓繼承機(jī)制的“利”大于“弊”?引入里氏替換原則里氏替換原則最正宗的定義:Ifforeachobjecto1oftypeSthereisanobjecto2oftypeTsuchthatforallprogramsPdefinedintermsofT,thebehaviorofPisunchangedwheno1issubstitutedforo2thenSisasubtypeofT.(如果對(duì)每一個(gè)類型為S的對(duì)象o1,都有類型為T的對(duì)象o2,使得以T定義的所有程序P在所有的對(duì)象o1都代換成o2時(shí),程序P的行為沒(méi)有發(fā)生變化,那么類型S是類型T的子類型。)里氏替換原則通俗講,只要父類出現(xiàn)的地方子類就可以出現(xiàn),而且替換為子類也不會(huì)產(chǎn)生任何錯(cuò)誤或異常,使用者可能根本就不需要知道是父類還是子類。但是反過(guò)來(lái)就不行了,有子類出現(xiàn)的地方,父類未必就能適應(yīng)。1、子類完全繼承父類的方法代碼清單場(chǎng)景類源碼Publicclassclient{Publicstaticvoidmain(string[]args){//產(chǎn)生三毛這個(gè)士兵SoldiersanMao=newSoldier();//給三毛一支槍sanMao.setGun(newRifle());sanMao.killEnemy();}}結(jié)果:士兵開(kāi)始?xì)橙恕綐屔鋼簟⒁猓涸陬愔姓{(diào)用其他類時(shí)務(wù)必要使用父類或接口,如果不能使用父類或接口,則說(shuō)明類的設(shè)計(jì)已經(jīng)違背了LSP原則。問(wèn):如果有一個(gè)玩具槍呢?里氏替換原則玩具槍不能殺敵,射不出子彈,在這種情況下,我們發(fā)現(xiàn)業(yè)務(wù)調(diào)用類已經(jīng)出現(xiàn)了問(wèn)題,正常的業(yè)務(wù)邏輯已經(jīng)不能運(yùn)行,怎么辦??jī)煞N解決辦法:在Soldier類中增加instanceof的判斷,如果是玩具槍,就不用來(lái)殺敵人。這個(gè)方法可以解決問(wèn)題,但是要知道,在程序中,每增加一個(gè)類,所有與這個(gè)父類有關(guān)的類都必須修改,可行嗎?ToyGun脫離繼承,建立一個(gè)獨(dú)立的父類,為了實(shí)現(xiàn)代碼復(fù)用,可以與AbastractGun建立關(guān)聯(lián)委托關(guān)系。如下圖里氏替換原則注意:如果子類不能完整地實(shí)現(xiàn)父類的方法,或者父類的某些方法在子類中已經(jīng)發(fā)生“畸變”,則建議斷開(kāi)父子繼承關(guān)系,采用依賴、聚集、組合等關(guān)系代替繼承。2、子類可以有自己的個(gè)性子類當(dāng)然可以有自己的行為和外觀了,也就是方法和屬性,那這里為什么要再提呢?是因?yàn)槔锸咸鎿Q原則可以正著用,但是不能反過(guò)來(lái)用。在子類出現(xiàn)的地方,父類未必就可以勝任。在這里,系統(tǒng)直接調(diào)用了子類,狙擊手是很依賴槍支的,別說(shuō)換一個(gè)型號(hào)的槍了,就是換一個(gè)同型號(hào)的槍也會(huì)影響射擊,所以這里就直接把子類傳遞了進(jìn)來(lái)。這個(gè)時(shí)候,我們能不能直接使用父類傳遞進(jìn)來(lái)呢?里氏替換原則3、覆蓋或?qū)崿F(xiàn)父類的方法時(shí)輸入?yún)?shù)可以被放大4、復(fù)寫(xiě)或?qū)崿F(xiàn)父類的方法時(shí)輸出結(jié)果可以被縮小依賴倒置原則依賴倒置原則(DependenceInversionPrinciple,DIP):Highlevelmodulesshouldnotdependuponlowlevelmodules.Bothshoulddependuponabstractions.Abstractionsshouldnotdependupondetails.Detailsshoulddependuponabstractions.依賴倒置原則依賴倒置原則包含三層含義:高層模塊不應(yīng)該依賴低層模塊,兩者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細(xì)節(jié);細(xì)節(jié)應(yīng)該依賴抽象。在java語(yǔ)言中,抽象就是指接口或抽象類,兩者都是不能直接被實(shí)例化的;細(xì)節(jié)就是實(shí)現(xiàn)類,實(shí)現(xiàn)接口或繼承抽象類而產(chǎn)生的類就是細(xì)節(jié),其特點(diǎn)就是可以直接被實(shí)例化,也就是可以加上一個(gè)關(guān)鍵字new產(chǎn)生一個(gè)對(duì)象。依賴倒置原則依賴倒置原則在java語(yǔ)言中的表現(xiàn)就是:模塊間的依賴通過(guò)抽象發(fā)生,實(shí)現(xiàn)類之間不發(fā)生直接的依賴關(guān)系,其依賴關(guān)系是通過(guò)接口或抽象類產(chǎn)生的;接口或抽象類不依賴于實(shí)現(xiàn)類;實(shí)現(xiàn)類依賴接口或抽象類。采用依賴倒置原則可以減少類間的耦合性,提高系統(tǒng)的穩(wěn)定性,降低并行開(kāi)發(fā)引起的風(fēng)險(xiǎn),提高代碼的可讀性和可維護(hù)性。注意:設(shè)計(jì)是否具備穩(wěn)定性,只要適當(dāng)?shù)亍八伤赏痢保^察“設(shè)計(jì)的藍(lán)圖”是否還可以茁壯地成長(zhǎng)就可以得出結(jié)論,穩(wěn)定性較高的設(shè)計(jì),在周圍環(huán)境頻繁變化的時(shí)候,依然可以做到“我自巋然不動(dòng)”。在20世紀(jì)90年代“個(gè)人英雄主義”編程模式還是比較適用的,一個(gè)人完成所有的代碼工作。但在現(xiàn)在的大中型項(xiàng)目中已經(jīng)完全不能勝任了,一個(gè)項(xiàng)目是一個(gè)團(tuán)隊(duì)協(xié)作的結(jié)果,一個(gè)“英雄”再厲害也不可能了解所有的業(yè)務(wù)和所有的技術(shù),要協(xié)作就要并行開(kāi)發(fā),要并行開(kāi)發(fā)就要解決模塊之間的項(xiàng)目依賴關(guān)系,那么就需要依賴倒置原則。在業(yè)務(wù)場(chǎng)景中,我們貫徹“抽象不應(yīng)該依賴細(xì)節(jié)”,也就是我們認(rèn)為抽象(ICar接口)不依賴BMW和Benz兩個(gè)實(shí)現(xiàn)類(細(xì)節(jié)),因此在高層次的模塊中應(yīng)用都是抽象。Client屬于高層業(yè)務(wù)邏輯,它對(duì)低層模塊的依賴都建立在抽象上,zhangSan的表面類型是IDriver,Benz的表面類型是ICar,是一個(gè)接口,是抽象的、非實(shí)體化的,在其后的所有操作中,zhangSan都是以IDriver類型進(jìn)行操作,屏蔽了細(xì)節(jié)對(duì)抽象的影響。當(dāng)然,張三如果要開(kāi)寶馬車,也很容易,我們只要修改業(yè)務(wù)場(chǎng)景類就可以實(shí)現(xiàn)。在增加低層模塊時(shí),只修改了業(yè)務(wù)場(chǎng)景類,也就是高層模塊,對(duì)其他低層模塊如Driver類不需要做任何修改,業(yè)務(wù)就可以運(yùn)行,把“變更”引起的風(fēng)險(xiǎn)擴(kuò)散降低到最小。注意:在java中,只要定義變量就必然要有類型,一個(gè)變量可以有兩種類型:表面類型和實(shí)際類型,表面類型是在定義的時(shí)候賦予的類型,實(shí)際類型是對(duì)象的類型,如zhangSan的表面類型是IDriver,實(shí)際類型是Driver。我們?cè)賮?lái)思考依賴倒置對(duì)并行開(kāi)發(fā)的影響。兩個(gè)類之間有依賴關(guān)系,只要制定出兩者之間的接口(或抽象類)就可以獨(dú)立開(kāi)發(fā)了。依賴的三種寫(xiě)法依賴是可以傳遞的,A對(duì)象依賴B對(duì)象,B又依賴C,C又依賴D……生生不息,依賴不止,記住一點(diǎn):只要做到抽象依賴,即使是多層的依賴傳遞也無(wú)所畏懼!對(duì)象的依賴關(guān)系有三種方式來(lái)傳遞,構(gòu)造函數(shù)傳遞依賴對(duì)象Setter方法傳遞依賴對(duì)象接口聲明依賴對(duì)象1.構(gòu)造函數(shù)傳遞依賴對(duì)象在類中通過(guò)構(gòu)造函數(shù)聲明依賴對(duì)象,按照依賴注入的說(shuō)法,這種方式叫做構(gòu)造函數(shù)注入,按照這種方式的注入,IDriver和Driver的程序修改后代碼如下:2.Setter方法傳遞依賴對(duì)象在抽象中設(shè)置Setter方法聲明依賴關(guān)系,依照依賴注入的說(shuō)法,這事Setter依賴注入,按照這種方式的注入,IDriver和Driver的程序修改后代碼如下:3.接口聲明依賴對(duì)象在接口的方法中聲明依賴對(duì)象,代碼清單3-6就是采用了接口聲明依賴的方式,該方法也叫做接口注入。依賴倒置原則優(yōu)點(diǎn)依賴倒置原則的優(yōu)點(diǎn)在小型項(xiàng)目中很難體現(xiàn)出來(lái),但是在一個(gè)大中型項(xiàng)目中,采用依賴倒置原則有非常多的優(yōu)點(diǎn),特別是規(guī)避一些非技術(shù)因素引起的問(wèn)題。項(xiàng)目越大,需求變化的概率也越大,通過(guò)采用依賴倒置原則設(shè)計(jì)的接口或抽象類對(duì)實(shí)現(xiàn)類進(jìn)行約束,可以減少需求變化引起的工作量劇增的情況。人員變動(dòng)在大中型項(xiàng)目的維護(hù)周期一般都很長(zhǎng),采用依賴倒置原則可以讓維護(hù)人員輕松地?cái)U(kuò)展和維護(hù)。依賴倒置原則與開(kāi)閉原則依賴倒置原則是6個(gè)原則中最難以實(shí)現(xiàn)的原則,它是實(shí)現(xiàn)開(kāi)閉原則的重要途徑,依賴倒置原則沒(méi)有實(shí)現(xiàn),就別想實(shí)現(xiàn)對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。在項(xiàng)目中,大家只要記住是“面向接口編程”就基本上抓住了依賴倒置原則的核心。接口隔離原則接口隔離原則定義:客戶端不應(yīng)該依賴它不需要的接口;類間的依賴關(guān)系應(yīng)該建立在最小的接口上。建立單一接口,不要建立臃腫龐大的接口,接口盡量細(xì)化,同時(shí)接口中的方法盡量少。它要求“盡量使用多個(gè)專門的接口”。專門接口指提供給每個(gè)模塊的都應(yīng)該是單一接口,提供給幾個(gè)模塊就應(yīng)該有幾個(gè)接口,而不是建立一個(gè)龐大的臃腫接口,容納所有的客戶端訪問(wèn)。美女何其多,觀點(diǎn)各不同問(wèn)題與改進(jìn)思考一下IPettyGirl這個(gè)接口,這個(gè)接口是否做到了最優(yōu)化設(shè)計(jì)?接口IPettyGirl的設(shè)計(jì)是有缺陷的,過(guò)于龐大了,容納了一些可變的因素,根據(jù)接口隔離原則,星探AbstractSearcher應(yīng)該依賴于具有部分特質(zhì)的女孩子,而我們卻把這些特質(zhì)都封裝了起來(lái),放到了一個(gè)接口中,封裝過(guò)度了!以上把一個(gè)臃腫的接口變更為兩個(gè)獨(dú)立的接口所依賴的原則就是接口隔離原則,讓星探AbstractSearcher依賴兩個(gè)專用的接口比依賴一個(gè)綜合的接口要靈活。接口是我們?cè)O(shè)計(jì)時(shí)對(duì)外提供的契約,通過(guò)分散定義多個(gè)接口,可以預(yù)防未來(lái)變更的擴(kuò)散,提高系統(tǒng)的靈活性和可維護(hù)性。接口隔離原則包含以下4層含義:接口要盡量?。骸靶 笔怯上薅鹊?,首先就是不能違反單一職責(zé)原則。接口要高內(nèi)聚:要求在接口中盡量少公布public方法,接口是對(duì)外的承諾,承諾越少對(duì)系統(tǒng)的開(kāi)發(fā)越有利,變更的風(fēng)險(xiǎn)也就越少,同時(shí)也有利于降低成本。定制服務(wù):定制服務(wù)就是單獨(dú)為一個(gè)個(gè)體提供優(yōu)良的服務(wù)。接口設(shè)計(jì)是有限度地迪米特法則迪米特法則的定義:迪米特法則(LawofDemeter,LoD)也稱為最少知識(shí)原則,一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有最少的了解。一個(gè)類應(yīng)該對(duì)自己需要耦合或調(diào)用的類知道得最少,被耦合或調(diào)用的類的內(nèi)部如何復(fù)雜都和我沒(méi)有關(guān)系,那是你的事情,我就知道你提供的這么多public方法,我就調(diào)用這么多,其他的我一概不關(guān)心。迪米特法則對(duì)類的低耦合提出了明確的要求:1.只和朋友交流朋友類:出現(xiàn)在成員變量、方法的輸入輸出參數(shù)中的類稱為成員朋友類,而出現(xiàn)在方法體內(nèi)部的類不屬于朋友類。注意:一個(gè)類只和朋友交流,不與陌生類交流,不要出現(xiàn)getA().getB().GetC().getD()這種情況,類與類之間的關(guān)系是建立在類間的,而不是方法見(jiàn),因此一個(gè)方法盡量不引入一個(gè)類中不存在的對(duì)象,當(dāng)然,JDKAPI提供的類除外。2.朋友間也是有距離的朋友

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論