只要是一再重复出现的事物_第1页
只要是一再重复出现的事物_第2页
只要是一再重复出现的事物_第3页
只要是一再重复出现的事物_第4页
只要是一再重复出现的事物_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

DesignPattern初探II李俊宏2009/4/231什麼是DesignPattern只要是一再重複出現的事物,就是Pattern。第四台廣告中的Pattern原價...,現在購買只要...,還送你一組...,請馬上來電...,如忙線中請稍後再撥。利用分割畫面顯示出使用前使用後的差別,來加強說服力。例如:由C升級到E找人現身說法:「傑瑞!感謝你介紹這套歐萊禮Java系列,讓我在短短的三個月內成為公司內首屈一指的Java專家,這實在是太神奇了!」選舉時的Pattern質疑對手A錢或搞婚外情把家人通通拉上台痛哭一場以示選情告急開口唱「愛拼才會贏」電影中的Pattern壞人追殺好人時,好人躲進車子,卻發現車子發不動,引擎嘎嘎作響,一面努力地繼續發動,一面念念有詞「Comeon,Comeon」。壞人追殺好人時,好人衝進電梯,死命地押著close按鈕,脫口而出「Comeon,Comeon」。電影最後,壞人和好人大對決,最後好人勝利,但是好人如果直接把壞人宰了,那好人在觀眾心中的形象就會受損,所以好人先饒壞人一條生路,但是壞人卻壞到骨子裡了,偷偷拿出一把槍瞄準好人,說時遲那時快,好人機警地察覺,為了自保於是將壞人一槍斃命。這個Pattern可以讓好人有人性,又讓壞人死有餘辜。

摘錄自蔡學傭先生文章什麼是DesignPatternPattern就是一種「千錘百鍊」的智慧結晶。有經驗的專家和沒經驗的新手,差別就在於:有經驗的專家知道如何在適當的時機,套用某些公式(Pattern)以解決特定的問題,這是專家經年累月所培養出來的Know-How什麼是DesignPattern物件導向軟體開發的程序OOA(物件導向分析)OOD(物件導向設計)OOP(物件導向程式設計)DesignPattern在OOD(Object-OrientedDesign)階段所採用的Pattern。運用良好的DesignPattern,可以使得系統架構更優良(也更快完成),對於後續的OOP、測試、維護,都會有很大的幫助。DesignPattern會告訴你,什麼情況下用Delegation而不要用繼承、什麼情況下用Interface而不要用Class...諸如此類的知識。這些都是軟體界前輩的智慧結晶。

InterfaceInterface規定了一組契約(method),所有實作它的類別都要實作所有方法。Client呼叫的是Interface中的方法,所以元件的抽換對Client來說是感覺不到的(不用改code)。實作界面就可保証符合規格Pattern2:Adapter/WrapperACAdapterDC12VAC110VExample1:BannerclassdiagramAC100VAdapterDC12V若你有一個這樣的寫好的或是舊的物件想在主程式使用它Banner.javapublicclassBanner{privateStringstring;publicBanner(Stringstring){

this.string=string;}publicvoidshowWithParen(){

System.out.println("("+string+")");}publicvoidshowWithAster(){

System.out.println("*"+string+"*");}}Print.java/PrintBanner.javapublicinterfacePrint{publicabstractvoidprintWeak();publicabstractvoidprintStrong();}publicclassPrintBanner

extendsBannerimplementsPrint{publicPrintBanner(Stringstring){

super(string);}publicvoidprintWeak(){

showWithParen();}publicvoidprintStrong(){

showWithAster();}}Main.javapublicclassMain{publicstaticvoidmain(String[]args){Printp=newPrintBanner("Hello");

p.printWeak();//(Hello)

p.printStrong();//*Hello*}}Main並不知道PrintBanner的實作Example2:Bannerclassdiagram(delegation)ThedifferenceBanner.javapublicclassBanner{privateStringstring;publicBanner(Stringstring){

this.string=string;}publicvoidshowWithParen(){

System.out.println("("+string+")");}publicvoidshowWithAster(){

System.out.println("*"+string+"*");}}Print.java/PrintBanner.javapublicinterfacePrint{publicabstractvoidprintWeak();publicabstractvoidprintStrong();}publicclassPrintBannerextendsPrint{

privateBannerbanner;publicPrintBanner(Stringstring){

this.banner=newBanner(string);}publicvoidprintWeak(){

banner.showWithParen();}publicvoidprintStrong(){

banner.showWithAster();}}Main.javapublicclassMain{publicstaticvoidmain(String[]args){Printp=newPrintBanner("Hello");

p.printWeak();

p.printStrong();}}Discussion(participants)Target:DC12V,printClient:computer,MainclassAdaptee:AC110V,BannerclassAdapter:ACadapter,PrintBannerclassDiscussionDiscussionClassesarelooselycoupleSourcecodeisnotnecessary(methodA…)Programmerdoesn'tneedtomodifysourcecode(methodA…)VersioncompatibilityisbetterMyProgramVersion1.0Version1.0SupportingProgramMyProgramVersion2.0Version1.0SupportingProgramVersion2.0SupportingProgram1.0-2.0adapterAnapplication當MyProgram昇級到2.0版時support1.0版的程式還可透過轉換器繼續使用Pattern3:方法範本TemplateMethod12345TemplateMethod12345123412452345TemplateMethodPattern在父類別指定處理大綱,在子類別處理規定具體內容程式範例功能性需求請寫出一個程式讓它可以在螢幕上印出<<HHHHH>>or<<BBBBB>>其中<<是開始的符號,>>是結束的符號,H是使用者輸入的字元每次都會印5次輸入符號非功能性需求可維護性和可擴充性使用者可能會改變開始和結束符號請寫出一個程式可以滿足以上需求+-------+|你好。||你好。||你好。||你好。||你好。|+-------+抽象方法實作預先實作display方法時的內容(固定的部份)open();

for(inti=0;i<5;i++){

print();}

close();

底下的class實作open,print,close的方法AbstractDisplay

類別publicabstractclassAbstractDisplay{//抽象類別AbstractDisplaypublicabstractvoidopen();//由子類別實作的抽象方法(1)openpublicabstractvoidprint();//由子類別實作的抽象方法(2)printpublicabstractvoidclose();//由子類別實作的抽象方法(3)closepublicfinalvoiddisplay(){//在此抽象類別中實作的方法displayopen();//先open…for(inti=0;i<5;i++){//反覆5次print…print();}close();//…最後close起來。這就是實作display方法時的內容

}}CharDisplayclasspublicclassCharDisplayextendsAbstractDisplay{//CharDisplay是AbstractDisplay

//的子類別。

privatecharch; //應輸出的字元。

publicCharDisplay(char

ch){ //把以建構子傳遞過來的字元ch

this.ch=ch; //儲存在欄位內。

}publicvoidopen(){ //本來在父類別時是抽象方法。

//這裡覆寫(override)後實作。

System.out.print("<<"); //輸出"<<"做為開始字串。

}publicvoidprint(){ //print方法也是在此實作。它是從display

//被重複呼叫出來。

System.out.print(ch); //輸出1個儲存在欄位的字元。

}publicvoidclose(){ //close方法也是在此實作。

System.out.println(">>"); //輸出結束字串">>"。

}}StringDisplaypublicclassStringDisplayextendsAbstractDisplay{//StringDisplay也是AbstractDisplay的子類別。

privateStringstring;//應輸出的字串。

privateintwidth;//以byte為單位所求出的字串「寬度」。

publicStringDisplay(Stringstring){//把以建構子傳遞過來的字串string

this.string=string;//儲存在欄位內。

this.width=string.getBytes().length;//接著把以byte為單位的字元寬幅也先

//儲存在欄位,後面還會使用到。

}publicvoidopen(){//先覆寫後再定義的open方法。

printLine();//以此類別的方法printLine畫出線段。

}publicvoidprint(){//print方法則在欄位所儲存的字串前後

System.out.println("|"+string+"|");//加上"|",然後輸出到畫面上。}publicvoidclose(){ //close方法則同

printLine(); //open,利用printLine方法畫出現段。

}privatevoidprintLine(){ //這是open和close所呼叫的printLine方法。

//因為這是private,所以只能在此類別內使用。

System.out.print("+"); //輸出"+"記號表示邊框位置。

for(inti=0;i<width;i++){ //輸出width個"-",

System.out.print("-"); //當作線段。

}

System.out.println("+"); //輸出"+"記號表示邊框位置。

}}MainclasspublicclassMain{publicstaticvoidmain(String[]args){

//建立1個有'H'的CharDisplay的物件個體。

AbstractDisplayd1=newCharDisplay('H');

//建立1個有"Hello,world."的StringDisplay的物件個體。

AbstractDisplayd2=newStringDisplay("Hello,world.");

//建立1個有"你好。"的StringDisplay的物件個體。

AbstractDisplayd3=newStringDisplay("你好。");d1.display();

//d1,d2,d3都是AbstractDisplay的子類別的物件個體,因此,

d2.display(); //可以呼叫繼承到的display方法。

d3.display(); //實際動作則規定在類別CharDisplay、}//StringDisplay。}有何好處?抽象方法實作預先實作display方法時的內容open();for(inti=0;i<5;i++){print();}close();底下的class實作open,print,close的方法若有一天使用者要改共同的部份,便不用一個一個的改實作物件Pattern4:Strategy把演算法則整個換掉Strategy:戰略程式範例假如我們要設計一個剪刀石頭布的二人自動對戰遊戲程式目前程式可在一開始選用二種不同的猜拳策略猜贏之後繼續出同樣的招式從上一次出的招式,以機率分配方式求出下一個招式的機率Hand:手勢的類別Strategy:猜拳戰略的抽象物件WinningStragety:猜贏之後繼續出同樣的招式戰略ProbStragety:從上一次出的招式,以機率分配方式求出下一個招式的機率Player:玩家類別HandClasspublicclassHand{publicstaticfinalintHANDVALUE_GUU=0;//表示石頭之值

publicstaticfinalintHANDVALUE_CHO=1;//表示剪刀之值

publicstaticfinalintHANDVALUE_PAA=2;//表示布之值

publicstaticfinalHand[]hand={//表示猜拳手勢的3個實例

newHand(HANDVALUE_GUU),newHand(HANDVALUE_CHO),newHand(HANDVALUE_PAA),};privatestaticfinalString[]name={//猜拳手勢的字串

"石頭","剪刀","布",};privateint

handvalue;//猜拳手勢之值

privateHand(int

handvalue){

this.handvalue=handvalue;}publicstaticHandgetHand(int

handvalue){//從值取得實例

returnhand[handvalue];}

publicboolean

isStrongerThan(Handh){//若this贏過h,則為truereturnfight(h)==1;}publicboolean

isWeakerThan(Handh){//若this輸給h,則為truereturnfight(h)==-1;}privateint

fight(Handh){//平手則為0,若this勝出則為1、若h勝出則為-1if(this==h){return0;}elseif((this.handvalue+1)%3==h.handvalue){return1;}else{return-1;}}publicStringtoString(){//轉換成字串

returnname[handvalue];}}石頭:0剪刀:1布:2布加一變石頭StrategyclasspublicinterfaceStrategy{publicabstractHandnextHand();publicabstractvoidstudy(booleanwin);}WinningStrategyclassimportjava.util.Random;publicclassWinningStrategyimplementsStrategy{privateRandomrandom;privatebooleanwon=false;privateHandprevHand;publicWinningStrategy(intseed){random=newRandom(seed);}publicHandnextHand(){if(!won){

prevHand=Hand.getHand(random.nextInt(3));}returnprevHand;}publicvoidstudy(booleanwin){won=win;}}若輸則隨便出若贏則出和前一次一樣的ProbStrategyclassimportjava.util.Random;publicclassProbStrategyimplementsStrategy{privateRandomrandom;privateint

prevHandValue=0;privateint

currentHandValue=0;privateint[][]history={{1,1,1,},{1,1,1,},{1,1,1,},};publicProbStrategy(intseed){random=newRandom(seed);}參考之前的輸贏記錄機動更改手勢出現機率History[上一次的手勢][這次的手勢]History[0][0]=3石頭,之前出石頭時的獲勝次數History[0][1]=5石頭,之前出剪刀時的獲勝次數History[0][2]=7石頭,之前出布時的獲勝次數取大於0小於15的亂數0<x<=3出石頭3<x<=8出剪刀8<x<=15出布publicHandnextHand(){

intbet=random.nextInt(getSum(currentHandValue));

int

handvalue=0;if(bet<history[currentHandValue][0]){

handvalue=0;}elseif(bet<history[currentHandValue][0]+history[currentHandValue][1]){

handvalue=1;}else{

handvalue=2;}

prevHandValue=currentHandValue;

currentHandValue=handvalue;returnHand.getHand(handvalue);}privateint

getSum(int

hv){

intsum=0;for(inti=0;i<3;i++){sum+=history[hv][i];}returnsum;}publicvoidstudy(booleanwin){if(win){

history[prevHandValue][currentHandValue]++;}else{

history[prevHandValue][(currentHandValue+1)%3]++;

history[prevHandValue][(currentHandValue+2)%3]++;}}}PlayerclasspublicclassPlayer{privateStringname;privateStrategystrategy;privateint

wincount;privateint

losecount;privateint

gamecount;publicPlayer(Stringname,Strategystrategy){//得到姓名和戰略

=name;

this.strategy=strategy;}publicHandnextHand(){//向戰略請示手勢

returnstrategy.nextHand();}publicvoidwin(){//猜贏

strategy.study(true);

wincount++;

gamecount++;}publicvoidlose(){//猜輸

strategy.study(false);

losecount++;

gamecount++;}publicvoideven(){//平手

gamecount++;}publicStringtoString(){return"["+name+":"+gamecount+"games,"+wincount

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论