設(shè)計(jì)模式的六大原則實(shí)例_第1頁
設(shè)計(jì)模式的六大原則實(shí)例_第2頁
設(shè)計(jì)模式的六大原則實(shí)例_第3頁
設(shè)計(jì)模式的六大原則實(shí)例_第4頁
設(shè)計(jì)模式的六大原則實(shí)例_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、一、設(shè)計(jì)模式的六大原則1、開閉原則(Open Close Principle)開閉原則就是說對擴(kuò)展開放,對修改關(guān)閉。在程序需要進(jìn)行拓展的時(shí)候,不能去修改原有的代碼,實(shí)現(xiàn)一個(gè)熱插拔的效果。所以一句話概括就是:為了使程序的擴(kuò)展性好,易于維護(hù)和升級。想要達(dá)到這樣的效果,我們需要使用接口和抽象類。開閉原則是面向?qū)ο蟮目蓮?fù)用設(shè)計(jì)的第一塊基石。開閉原則的關(guān)鍵是抽象化。2、里氏代換原則(Liskov Substitution Principle)里氏代換原則(Liskov Substitution Principle LSP)面向?qū)ο笤O(shè)計(jì)的基本原則之一。 里氏代換原則中說,任何基類可以出現(xiàn)的地方,子類一定可

2、以出現(xiàn)。 LSP是繼承復(fù)用的基石,只有當(dāng)衍生類可以替換掉基類,軟件單位的功能不受到影響時(shí),基類才能真正被復(fù)用,而衍生類也能夠在基類的基礎(chǔ)上增加新的行為。里氏代換原則是對“開-閉”原則的補(bǔ)充。實(shí)現(xiàn)“開-閉”原則的關(guān)鍵步驟就是抽象化。而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里氏代換原則是對實(shí)現(xiàn)抽象化的具體步驟的規(guī)范。面向?qū)ο蟮脑O(shè)計(jì)關(guān)注的是對象的行為,它是使用“行為”來對對象進(jìn)行分類的,只有行為一致的對象才能抽象出一個(gè)類來。我經(jīng)常說類的繼承關(guān)系就是一種“Is-A”關(guān)系,實(shí)際上指的是行為上的“Is-A”關(guān)系,可以把它描述為“Act-As”。3、依賴倒轉(zhuǎn)原則(Dependence Inversi

3、on Principle)這個(gè)是開閉原則的基礎(chǔ),具體內(nèi)容:真對接口編程,依賴于抽象而不依賴于具體。4、接口隔離原則(Interface Segregation Principle)這個(gè)原則的意思是:使用多個(gè)隔離的接口,比使用單個(gè)接口要好。還是一個(gè)降低類之間的耦合度的意思,從這兒我們看出,其實(shí)設(shè)計(jì)模式就是一個(gè)軟件的設(shè)計(jì)思想,從大型軟件架構(gòu)出發(fā),為了升級和維護(hù)方便。所以上文中多次出現(xiàn):降低依賴,降低耦合。5、迪米特法則(最少知道原則)(Demeter Principle)最少知道原則,就是說:一個(gè)實(shí)體應(yīng)當(dāng)盡量少的與其他實(shí)體之間發(fā)生相互作用,使得系統(tǒng)功能模塊相對獨(dú)立。6、合成復(fù)用原則(Composi

4、te Reuse Principle)合成/聚合復(fù)用原則是在一個(gè)新的對象里面使用一些已有的對象,使之成為新對象的一部分;新的對象通過向這些對象的委派達(dá)到復(fù)用已有功能的目的。合成(Composition)和聚合(Aggregation)都是關(guān)聯(lián)(Association)的特殊種類。原則是盡量使用合成/聚合的方式,而不是使用繼承。11.開閉原則實(shí)例Fruit接口:抽象產(chǎn)品Orange類:實(shí)現(xiàn)fruit接口,具體產(chǎn)品Apple類:實(shí)現(xiàn)Fruit接口,具體產(chǎn)品Gardener接口:抽象工廠AppleGardener類:實(shí)現(xiàn)Gardener接口,具體工廠,分管apple生產(chǎn)OrangeGardener類

5、:實(shí)現(xiàn)Gardener接口,具體工廠,分管orange生產(chǎn)package com.zky.www.factory;public interface Fruit /水果接口public void plant();public void grow();public void harvest();public class Apple implements Fruit /蘋果實(shí)現(xiàn)水果接口public void grow() System.out.println(apple is growing!);public void harvest() System.out.println(apple is ha

6、rvesting!);public void plant() System.out.println(apple is planting!);public class Orange implements Fruit /桔子實(shí)現(xiàn)水果接口public void grow() System.out.println(orange is growing!);public void harvest() System.out.println(orange is harvesting!);public void plant() System.out.println(orange is planting!);pu

7、blic interface Gardener /園丁接口public Fruit getFruit();public class AppleGardener implements Gardener Overridepublic Fruit getFruit() return new Apple();public class OrangeGradener implements Gardener Overridepublic Fruit getFruit() return new Orange();public class Client public static void main(Strin

8、g args) Gardener g1=new AppleGardener();Apple apple=(Apple) g1.getFruit();apple.harvest();22、里氏代換原則實(shí)例正方形不是長方形package com.zky.www.liskov;public class Rectangle private double width;private double height;public Rectangle()public Rectangle(double width, double height) super();this.width = width;this.he

9、ight = height;public double getWidth() return width;public void setWidth(double width) this.width = width;public double getHeight() return height;public void setHeight(double height) this.height = height;package com.zky.www.liskov;public class Square extends Rectangle private double side;public Squa

10、re(double side) super();this.side = side;public double getSide() return side;public void setSide(double side) this.side = side;package com.zky.www.liskov;public class SmartTest public void resize(Rectangle r)while (r.getHeight()=r.getWidth()r.setWidth(r.getWidth()+1);33、依賴倒轉(zhuǎn)原則實(shí)例publicclassBenz /汽車肯定

11、會跑 publicvoidrun() System.out.println(奔馳汽車開始運(yùn)行.); publicclassDriver /司機(jī)的主要職責(zé)就是駕駛汽車 publicvoiddrive(Benz benz) benz.run(); publicclassClient publicstaticvoidmain(String args) Driver zhangSan = newDriver(); Benz benz = newBenz(); /張三開奔馳車 zhangSan.drive(benz); 上面實(shí)例,司機(jī)張三只能開奔馳車,不能開其他車,因此設(shè)計(jì)出了問題,改正如下。publi

12、cinterfaceIDriver /是司機(jī)就應(yīng)該會駕駛汽車 publicvoiddrive(ICar car); publicclassDriver implementsIDriver /司機(jī)的主要職責(zé)就是駕駛汽車 publicvoiddrive(ICar car) car.run(); publicinterfaceICar /是汽車就應(yīng)該能跑 publicvoidrun(); publicclassBenz implementsICar /汽車肯定會跑 publicvoidrun() System.out.println(奔馳汽車開始運(yùn)行.); publicclassBMW implem

13、entsICar /寶馬車當(dāng)然也可以開動了 publicvoidrun() System.out.println(寶馬汽車開始運(yùn)行.); 在業(yè)務(wù)場景中,我們貫徹“抽象不應(yīng)該依賴細(xì)節(jié)”,也就是我們認(rèn)為抽象(ICar接口)不依賴BMW和Benz兩個(gè)實(shí)現(xiàn)類(細(xì)節(jié)),因此我們在高層次的模塊中應(yīng)用都是抽象,Client的實(shí)現(xiàn)過程如下:public class Client public static void main(String args) IDriver zhangSan = new Driver();ICar benz = new Benz();/張三開奔馳車zhangSan.drive(ben

14、z); Client屬于高層業(yè)務(wù)邏輯,它對低層模塊的依賴都建立在抽象上,zhangSan的顯示類型是IDriver,benz的顯示類型是ICar,也許你要問,在這個(gè)高層模塊中也調(diào)用到了低層模塊,比如new Driver()和new Benz()等,如何解釋?確實(shí)如此,zhangSan的顯示類型是IDriver,是一個(gè)接口,是抽象的,非實(shí)體化的,在其后的所有操作中,zhangSan都是以IDriver類型進(jìn)行操作,屏蔽了細(xì)節(jié)對抽象的影響。當(dāng)然,張三如果要開寶馬車,也很容易,我們只要修改業(yè)務(wù)場景類就可以。注意在Java中,只要定義變量就必然要有類型,一個(gè)變量可以有兩個(gè)類型:顯示類型和真實(shí)類型,顯示

15、類型是在定義的時(shí)候賦予的類型,真實(shí)類型是對象的類型,如zhangSan的顯示類型是IDriver,真實(shí)類型是Driver。44.接口隔離原則public interface IPettyGirl /要有姣好的面孔public void goodLooking();/要有好身材public void niceFigure();/要有氣質(zhì)public void greatTemperament();public class PettyGirl implements IPettyGirl private String name;/美女都有名字public PettyGirl(String name)

16、 this. name=name; /臉蛋漂亮public void goodLooking() System. out.println(this. name + -臉蛋很漂亮!); /氣質(zhì)要好public void greatTemperament() System. out.println(this. name + -氣質(zhì)非常好!); /身材要好public void niceFigure() System. out.println(this. name + -身材非常棒!); public abstract class AbstractSearcher protected IPettyG

17、irl pettyGirl;public AbstractSearcher(IPettyGirl _pettyGirl) this.pettyGirl = _pettyGirl; /搜索美女,列出美女信息public abstract void show();public class Searcher extends AbstractSearcherpublic Searcher(IPettyGirl _pettyGirl) super(_pettyGirl); /展示美女的信息public void show() System. out.println(-美女的信息如下: -); /展示面容

18、 super. pettyGirl.goodLooking(); /展示身材super. pettyGirl.niceFigure(); /展示氣質(zhì) super. pettyGirl.greatTemperament(); public class Client /搜索并展示美女信息public static void main(String args) /定義一個(gè)美女 IPettyGirl yanYan = new PettyGirl(嫣嫣); AbstractSearcher searcher = new Searcher(yanYan); searcher.show(); 如果星探想找有

19、內(nèi)在氣質(zhì)的,不找外形漂亮的,怎么辦?看來IPettyGirl接口功能有些臃腫,因此把原 IPettyGirl 接口拆分為兩個(gè)接口,一種是外形美的美女 IGoodBodyGirl,這類美女的特點(diǎn)就是臉 蛋和身材極棒,超一流,但是沒有審美素質(zhì),比如隨地吐痰,出口就是臟話,文化程度比較低; 另外一種是氣質(zhì)美的美女 IGreatTemperamentGirl,談吐和修養(yǎng)都非常高。我們從一個(gè)比較臃腫的接口拆分 成了兩個(gè)專門的接口,靈活性提高了,可維護(hù)性也增加了,不管以后是要外形美的美女還是氣質(zhì)美的美女 都可以輕松的通過 PettyGirl 定義。我們先看兩種類型的美女接口:public interfac

20、e IGoodBodyGirl /要有姣好的面孔public void goodLooking();/要有好身材public void niceFigure();public interface IGreatTemperamentGirl /要有氣質(zhì)public void greatTemperament();實(shí)現(xiàn)類沒有改變,只是實(shí)現(xiàn)類兩個(gè)接口,源碼如下:public class PettyGirl implements IGoodBodyGirl,IGreatTemperamentGirl private String name;/美女都有名字public PettyGirl(String

21、_name) this. name=_name; /臉蛋漂亮public void goodLooking() System. out.println(this. name + -臉蛋很漂亮!); /氣質(zhì)要好public void greatTemperament() System. out.println(this. name + -氣質(zhì)非常好!); /身材要好public void niceFigure() System. out.println(this. name + -身材非常棒!); 通過這樣的改造以后,不管以后是要?dú)赓|(zhì)美女還是要外形美女,都可以保持接口的穩(wěn)定。當(dāng)然你可能 要說了,

22、以后可能審美觀點(diǎn)再發(fā)生改變,只有臉蛋好看就是美女,那這個(gè) IGoodBody 接口還是要修改的呀, 確實(shí)是,但是設(shè)計(jì)時(shí)有限度的,不能無限的考慮未來的變更情況,否則就會陷入設(shè)計(jì)的泥潭中而不能自拔。 以上把一個(gè)臃腫的接口變更為兩個(gè)獨(dú)立的接口依賴的原則就是接口隔離原則,讓 AbstractSearcher 依 賴兩個(gè)專用的接口比依賴一個(gè)綜合的接口要靈活。接口是我們設(shè)計(jì)時(shí)對外提供的契約,通過分散定義多個(gè) 接口,可以預(yù)防未來變更的擴(kuò)散,提高系統(tǒng)的靈活性和可維護(hù)性。55.迪米特法則如果兩個(gè)類不必彼此直接通信,那么這兩個(gè)類就不應(yīng)當(dāng)發(fā)生直接的相互作用。如果其中的一個(gè)類需要調(diào)用另外一個(gè)類的某一個(gè)方法,可以通過第

23、三者轉(zhuǎn)發(fā)這個(gè)調(diào)用。參考下例,Someone、Friend和Stranger三個(gè)類。publicclassSomeonepublicvoidoperation1(Friendfriend)Strangerstranger=vide();stranger.operation3();所以Someone和Friend是朋友類(直接通訊的類)。同理,F(xiàn)riend類持有一個(gè)Stranger類的私有對象,他們是朋友類:publicclassFriendprivateStrangerstranger=newStranger();publicvoidoperation2()publicStr

24、angerprovide()returnstranger;在這里,Someone類和Stranger類不是朋友類,但Someone類卻通過Friend類知道了Stranger類的存在,這顯然違反迪米特法則。現(xiàn)在,我們對Someone和Friend類進(jìn)行重構(gòu)。首先在Friend類里添加一個(gè)方法,封裝對Stranger類的操作:publicclassFriendprivateStrangerstranger=newStranger();publicvoidoperation2()publicStrangerprovide()returnstranger;publicvoidforward()str

25、anger.operation3();然后,我們重構(gòu)Someone的operation1方法,讓其調(diào)用新提供的forward方法:publicclassSomeonepublicvoidoperation1(Friendfriend)friend.forward();現(xiàn)在Someone對Stranger的依賴完全通過Friend隔離,這樣的結(jié)構(gòu)已經(jīng)符合狹義迪米特法則了。仔細(xì)觀察上述結(jié)構(gòu),會發(fā)現(xiàn)狹義迪米特法則一個(gè)明顯的缺點(diǎn):會在系統(tǒng)里造出大量的小方法,散落在系統(tǒng)的各個(gè)角落。這些方法僅僅是傳遞間接的調(diào)用,因此與系統(tǒng)的商務(wù)邏輯無關(guān),當(dāng)設(shè)計(jì)師試圖從一張類圖看出總體的框架時(shí),這些小的方法會造成迷惑和困擾

26、。遵循迪米特法則會使一個(gè)系統(tǒng)的局部設(shè)計(jì)簡化,因?yàn)槊恳粋€(gè)局部都不會和遠(yuǎn)距離的對象有直接關(guān)聯(lián)。但是,這也會造成系統(tǒng)的不同模塊之間的通信效率降低,也會使系統(tǒng)的不同模塊之間不容易協(xié)調(diào)。結(jié)合依賴倒轉(zhuǎn)原則,我們對代碼進(jìn)行如下重構(gòu)來解決這個(gè)問題,首先添加一個(gè)抽象的Stranger類,使Someone依賴于抽象的“Stranger”角色,而不是具體實(shí)現(xiàn):publicabstractclassAbstractStrangerabstractvoidoperation3();然后,讓Stranger從該類繼承:publicclassStrangerextendsAbstractStrangerpublicvoid

27、operation3()隨后,我們重構(gòu)Someone使其依賴抽象的Stranger角色:publicclassSomeonepublicvoidoperation1(Friendfriend)AbstractStrangerstranger=vide();stranger.operation3();最后,我們重構(gòu)Friend的provide方法,使其返回抽象角色:publicclassFriendprivateStrangerstranger=newStranger();publicvoidoperation2()publicAbstractStrangerprovide(

28、)returnstranger;現(xiàn)在,AbstractStranger成為Someone的朋友類,而Friend類可以隨時(shí)替換掉AbstractStranger的實(shí)現(xiàn)類,Someone不再需要了解Stranger的內(nèi)部實(shí)現(xiàn)細(xì)節(jié)。下圖是重構(gòu)后的UML類圖:在將迪米特法則運(yùn)用到系統(tǒng)的設(shè)計(jì)中時(shí),應(yīng)注意的幾點(diǎn): 在類的劃分上,應(yīng)該創(chuàng)建有弱耦合的類; 在類的結(jié)構(gòu)設(shè)計(jì)上,每一個(gè)類都應(yīng)當(dāng)盡量降低成員的訪問權(quán)限; 在類的設(shè)計(jì)上,只要有可能,一個(gè)類應(yīng)當(dāng)設(shè)計(jì)成不變類; 在對其他類的引用上,一個(gè)對象對其它對象的引用應(yīng)當(dāng)降到最低; 盡量降低類的訪問權(quán)限; 謹(jǐn)慎使用序列化功能; 不要暴露類成員,而應(yīng)該提供相應(yīng)的訪問器(

29、屬性)。66、合成復(fù)用原則實(shí)例(1)聚合用來表示“擁有”關(guān)系或者整體與部分的關(guān)系。代表部分的對象有可能會被多個(gè)代表整體的對象所共享,而且不一定會隨著某個(gè)代表整體的對象被銷毀或破壞而被銷毀或破壞,部分的生命周期可以超越整體。例如,班級和學(xué)生,當(dāng)班級刪除后,學(xué)生還能存在,學(xué)生可以被培訓(xùn)機(jī)構(gòu)引用。class Student private String sName;class Classes private Student student; public Classes(Student student) this.student=student; (2)合成用來表示一種強(qiáng)得多的“擁有”關(guān)系。在一個(gè)合成關(guān)系里,部分和整體的生命周期是一樣的。一個(gè)合成的新對象完全擁有對其組成部分的支配權(quán),包括它們的創(chuàng)建和湮滅等。使用程序語言的術(shù)語來說,合成而成的新對象對組成部分的內(nèi)存分配、內(nèi)存釋放有絕對的責(zé)任。一個(gè)合成關(guān)系中的成分對象是不能與另一個(gè)合成關(guān)系共享的。一個(gè)成分對象在同一個(gè)時(shí)間內(nèi)只能屬于一個(gè)合成關(guān)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論