




已閱讀5頁,還剩51頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
一、設(shè)計(jì)模式的分類總體來說設(shè)計(jì)模式分為三大類:創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。結(jié)構(gòu)型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責(zé)任鏈模式、命令模式、備忘錄模式、狀態(tài)模式、訪問者模式、中介者模式、解釋器模式。其實(shí)還有兩類:并發(fā)型模式和線程池模式。用一個(gè)圖片來整體描述一下:二、設(shè)計(jì)模式的六大原則1、開閉原則(Open Close Principle)開閉原則就是說對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。在程序需要進(jìn)行拓展的時(shí)候,不能去修改原有的代碼,實(shí)現(xiàn)一個(gè)熱插拔的效果。所以一句話概括就是:為了使程序的擴(kuò)展性好,易于維護(hù)和升級(jí)。想要達(dá)到這樣的效果,我們需要使用接口和抽象類,后面的具體設(shè)計(jì)中我們會(huì)提到這點(diǎn)。2、里氏代換原則(Liskov Substitution Principle)里氏代換原則(Liskov Substitution Principle LSP)面向?qū)ο笤O(shè)計(jì)的基本原則之一。 里氏代換原則中說,任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。 LSP是繼承復(fù)用的基石,只有當(dāng)衍生類可以替換掉基類,軟件單位的功能不受到影響時(shí),基類才能真正被復(fù)用,而衍生類也能夠在基類的基礎(chǔ)上增加新的行為。里氏代換原則是對(duì)“開-閉”原則的補(bǔ)充。實(shí)現(xiàn)“開-閉”原則的關(guān)鍵步驟就是抽象化。而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里氏代換原則是對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范。 From Baidu 百科3、依賴倒轉(zhuǎn)原則(Dependence Inversion Principle)這個(gè)是開閉原則的基礎(chǔ),具體內(nèi)容:真對(duì)接口編程,依賴于抽象而不依賴于具體。4、接口隔離原則(Interface Segregation Principle)這個(gè)原則的意思是:使用多個(gè)隔離的接口,比使用單個(gè)接口要好。還是一個(gè)降低類之間的耦合度的意思,從這兒我們看出,其實(shí)設(shè)計(jì)模式就是一個(gè)軟件的設(shè)計(jì)思想,從大型軟件架構(gòu)出發(fā),為了升級(jí)和維護(hù)方便。所以上文中多次出現(xiàn):降低依賴,降低耦合。5、迪米特法則(最少知道原則)(Demeter Principle)為什么叫最少知道原則,就是說:一個(gè)實(shí)體應(yīng)當(dāng)盡量少的與其他實(shí)體之間發(fā)生相互作用,使得系統(tǒng)功能模塊相對(duì)獨(dú)立。6、合成復(fù)用原則(Composite Reuse Principle)原則是盡量使用合成/聚合的方式,而不是使用繼承。三、Java的23中設(shè)計(jì)模式從這一塊開始,我們?cè)敿?xì)介紹Java中23種設(shè)計(jì)模式的概念,應(yīng)用場(chǎng)景等情況,并結(jié)合他們的特點(diǎn)及設(shè)計(jì)模式的原則進(jìn)行分析。1、工廠方法模式(Factory Method)工廠方法模式分為三種:11、普通工廠模式,就是建立一個(gè)工廠類,對(duì)實(shí)現(xiàn)了同一接口的一些類進(jìn)行實(shí)例的創(chuàng)建。首先看下關(guān)系圖:舉例如下:(我們舉一個(gè)發(fā)送郵件和短信的例子)首先,創(chuàng)建二者的共同接口:java view plaincopy1 public interface Sender 2 public void Send(); 3 其次,創(chuàng)建實(shí)現(xiàn)類:java view plaincopy4 public class MailSender implements Sender 5 Override 6 public void Send() 7 System.out.println(this is mailsender!); 8 9 java view plaincopy10 public class SmsSender implements Sender 11 12 Override 13 public void Send() 14 System.out.println(this is sms sender!); 15 16 最后,建工廠類:java view plaincopy17 public class SendFactory 18 19 public Sender produce(String type) 20 if (mail.equals(type) 21 return new MailSender(); 22 else if (sms.equals(type) 23 return new SmsSender(); 24 else 25 System.out.println(請(qǐng)輸入正確的類型!); 26 return null; 27 28 29 我們來測(cè)試下:30 public class FactoryTest 31 32 public static void main(String args) 33 SendFactory factory = new SendFactory(); 34 Sender sender = duce(sms); 35 sender.Send(); 36 37 輸出:this is sms sender!22、多個(gè)工廠方法模式,是對(duì)普通工廠方法模式的改進(jìn),在普通工廠方法模式中,如果傳遞的字符串出錯(cuò),則不能正確創(chuàng)建對(duì)象,而多個(gè)工廠方法模式是提供多個(gè)工廠方法,分別創(chuàng)建對(duì)象。關(guān)系圖:將上面的代碼做下修改,改動(dòng)下SendFactory類就行,如下:java view plaincopypublic class SendFactory public Sender produceMail() 38 return new MailSender(); 39 40 41 public Sender produceSms() 42 return new SmsSender(); 43 44 測(cè)試類如下:java view plaincopy45 public class FactoryTest 46 47 public static void main(String args) 48 SendFactory factory = new SendFactory(); 49 Sender sender = duceMail(); 50 sender.Send(); 51 52 輸出:this is mailsender!33、靜態(tài)工廠方法模式,將上面的多個(gè)工廠方法模式里的方法置為靜態(tài)的,不需要?jiǎng)?chuàng)建實(shí)例,直接調(diào)用即可。java view plaincopy53 public class SendFactory 54 55 public static Sender produceMail() 56 return new MailSender(); 57 58 59 public static Sender produceSms() 60 return new SmsSender(); 61 62 java view plaincopy63 public class FactoryTest 64 65 public static void main(String args) 66 Sender sender = SendFduceMail(); 67 sender.Send(); 68 69 輸出:this is mailsender!總體來說,工廠模式適合:凡是出現(xiàn)了大量的產(chǎn)品需要?jiǎng)?chuàng)建,并且具有共同的接口時(shí),可以通過工廠方法模式進(jìn)行創(chuàng)建。在以上的三種模式中,第一種如果傳入的字符串有誤,不能正確創(chuàng)建對(duì)象,第三種相對(duì)于第二種,不需要實(shí)例化工廠類,所以,大多數(shù)情況下,我們會(huì)選用第三種靜態(tài)工廠方法模式。2、抽象工廠模式(Abstract Factory)工廠方法模式有一個(gè)問題就是,類的創(chuàng)建依賴工廠類,也就是說,如果想要拓展程序,必須對(duì)工廠類進(jìn)行修改,這違背了閉包原則,所以,從設(shè)計(jì)角度考慮,有一定的問題,如何解決?就用到抽象工廠模式,創(chuàng)建多個(gè)工廠類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,不需要修改之前的代碼。因?yàn)槌橄蠊S不太好理解,我們先看看圖,然后就和代碼,就比較容易理解。請(qǐng)看例子:java view plaincopy70 public interface Sender 71 public void Send(); 72 兩個(gè)實(shí)現(xiàn)類:java view plaincopy73 public class MailSender implements Sender 74 Override 75 public void Send() 76 System.out.println(this is mailsender!); 77 78 java view plaincopy79 public class SmsSender implements Sender 80 81 Override 82 public void Send() 83 System.out.println(this is sms sender!); 84 85 兩個(gè)工廠類:java view plaincopy86 public class SendMailFactory implements Provider 87 88 Override 89 public Sender produce() 90 return new MailSender(); 91 92 java view plaincopy93 public class SendSmsFactory implements Provider 94 95 Override 96 public Sender produce() 97 return new SmsSender(); 98 99 在提供一個(gè)接口:java view plaincopy100 public interface Provider 101 public Sender produce(); 102 測(cè)試類:java view plaincopy103 public class Test 104 105 public static void main(String args) 106 Provider provider = new SendMailFactory(); 107 Sender sender = duce(); 108 sender.Send(); 109 110 其實(shí)這個(gè)模式的好處就是,如果你現(xiàn)在想增加一個(gè)功能:發(fā)及時(shí)信息,則只需做一個(gè)實(shí)現(xiàn)類,實(shí)現(xiàn)Sender接口,同時(shí)做一個(gè)工廠類,實(shí)現(xiàn)Provider接口,就OK了,無需去改動(dòng)現(xiàn)成的代碼。這樣做,拓展性較好!3、單例模式(Singleton)單例對(duì)象(Singleton)是一種常用的設(shè)計(jì)模式。在Java應(yīng)用中,單例對(duì)象能保證在一個(gè)JVM中,該對(duì)象只有一個(gè)實(shí)例存在。這樣的模式有幾個(gè)好處:1、某些類創(chuàng)建比較頻繁,對(duì)于一些大型的對(duì)象,這是一筆很大的系統(tǒng)開銷。2、省去了new操作符,降低了系統(tǒng)內(nèi)存的使用頻率,減輕GC壓力。3、有些類如交易所的核心交易引擎,控制著交易流程,如果該類可以創(chuàng)建多個(gè)的話,系統(tǒng)完全亂了。(比如一個(gè)軍隊(duì)出現(xiàn)了多個(gè)司令員同時(shí)指揮,肯定會(huì)亂成一團(tuán)),所以只有使用單例模式,才能保證核心交易服務(wù)器獨(dú)立控制整個(gè)流程。首先我們寫一個(gè)簡(jiǎn)單的單例類:java view plaincopy111 public class Singleton 112 113 /* 持有私有靜態(tài)實(shí)例,防止被引用,此處賦值為null,目的是實(shí)現(xiàn)延遲加載 */ 114 private static Singleton instance = null; 115 116 /* 私有構(gòu)造方法,防止被實(shí)例化 */ 117 private Singleton() 118 119 120 /* 靜態(tài)工程方法,創(chuàng)建實(shí)例 */ 121 public static Singleton getInstance() 122 if (instance = null) 123 instance = new Singleton(); 124 125 return instance; 126 127 128 /* 如果該對(duì)象被用于序列化,可以保證對(duì)象在序列化前后保持一致 */ 129 public Object readResolve() 130 return instance; 131 132 這個(gè)類可以滿足基本要求,但是,像這樣毫無線程安全保護(hù)的類,如果我們把它放入多線程的環(huán)境下,肯定就會(huì)出現(xiàn)問題了,如何解決?我們首先會(huì)想到對(duì)getInstance方法加synchronized關(guān)鍵字,如下:java view plaincopy133 public static synchronized Singleton getInstance() 134 if (instance = null) 135 instance = new Singleton(); 136 137 return instance; 138 但是,synchronized關(guān)鍵字鎖住的是這個(gè)對(duì)象,這樣的用法,在性能上會(huì)有所下降,因?yàn)槊看握{(diào)用getInstance(),都要對(duì)對(duì)象上鎖,事實(shí)上,只有在第一次創(chuàng)建對(duì)象的時(shí)候需要加鎖,之后就不需要了,所以,這個(gè)地方需要改進(jìn)。我們改成下面這個(gè):java view plaincopy139 public static Singleton getInstance() 140 if (instance = null) 141 synchronized (instance) 142 if (instance = null) 143 instance = new Singleton(); 144 145 146 147 return instance; 148 似乎解決了之前提到的問題,將synchronized關(guān)鍵字加在了內(nèi)部,也就是說當(dāng)調(diào)用的時(shí)候是不需要加鎖的,只有在instance為null,并創(chuàng)建對(duì)象的時(shí)候才需要加鎖,性能有一定的提升。但是,這樣的情況,還是有可能有問題的,看下面的情況:在Java指令中創(chuàng)建對(duì)象和賦值操作是分開進(jìn)行的,也就是說instance = new Singleton();語句是分兩步執(zhí)行的。但是JVM并不保證這兩個(gè)操作的先后順序,也就是說有可能JVM會(huì)為新的Singleton實(shí)例分配空間,然后直接賦值給instance成員,然后再去初始化這個(gè)Singleton實(shí)例。這樣就可能出錯(cuò)了,我們以A、B兩個(gè)線程為例:aA、B線程同時(shí)進(jìn)入了第一個(gè)if判斷bA首先進(jìn)入synchronized塊,由于instance為null,所以它執(zhí)行instance = new Singleton();c由于JVM內(nèi)部的優(yōu)化機(jī)制,JVM先畫出了一些分配給Singleton實(shí)例的空白內(nèi)存,并賦值給instance成員(注意此時(shí)JVM沒有開始初始化這個(gè)實(shí)例),然后A離開了synchronized塊。dB進(jìn)入synchronized塊,由于instance此時(shí)不是null,因此它馬上離開了synchronized塊并將結(jié)果返回給調(diào)用該方法的程序。e此時(shí)B線程打算使用Singleton實(shí)例,卻發(fā)現(xiàn)它沒有被初始化,于是錯(cuò)誤發(fā)生了。所以程序還是有可能發(fā)生錯(cuò)誤,其實(shí)程序在運(yùn)行過程是很復(fù)雜的,從這點(diǎn)我們就可以看出,尤其是在寫多線程環(huán)境下的程序更有難度,有挑戰(zhàn)性。我們對(duì)該程序做進(jìn)一步優(yōu)化:java view plaincopy149 private static class SingletonFactory 150 private static Singleton instance = new Singleton(); 151 152 public static Singleton getInstance() 153 return SingletonFactory.instance; 154 實(shí)際情況是,單例模式使用內(nèi)部類來維護(hù)單例的實(shí)現(xiàn),JVM內(nèi)部的機(jī)制能夠保證當(dāng)一個(gè)類被加載的時(shí)候,這個(gè)類的加載過程是線程互斥的。這樣當(dāng)我們第一次調(diào)用getInstance的時(shí)候,JVM能夠幫我們保證instance只被創(chuàng)建一次,并且會(huì)保證把賦值給instance的內(nèi)存初始化完畢,這樣我們就不用擔(dān)心上面的問題。同時(shí)該方法也只會(huì)在第一次調(diào)用的時(shí)候使用互斥機(jī)制,這樣就解決了低性能問題。這樣我們暫時(shí)總結(jié)一個(gè)完美的單例模式:java view plaincopy155 public class Singleton 156 157 /* 私有構(gòu)造方法,防止被實(shí)例化 */ 158 private Singleton() 159 160 161 /* 此處使用一個(gè)內(nèi)部類來維護(hù)單例 */ 162 private static class SingletonFactory 163 private static Singleton instance = new Singleton(); 164 165 166 /* 獲取實(shí)例 */ 167 public static Singleton getInstance() 168 return SingletonFactory.instance; 169 170 171 /* 如果該對(duì)象被用于序列化,可以保證對(duì)象在序列化前后保持一致 */ 172 public Object readResolve() 173 return getInstance(); 174 175 其實(shí)說它完美,也不一定,如果在構(gòu)造函數(shù)中拋出異常,實(shí)例將永遠(yuǎn)得不到創(chuàng)建,也會(huì)出錯(cuò)。所以說,十分完美的東西是沒有的,我們只能根據(jù)實(shí)際情況,選擇最適合自己應(yīng)用場(chǎng)景的實(shí)現(xiàn)方法。也有人這樣實(shí)現(xiàn):因?yàn)槲覀冎恍枰趧?chuàng)建類的時(shí)候進(jìn)行同步,所以只要將創(chuàng)建和getInstance()分開,單獨(dú)為創(chuàng)建加synchronized關(guān)鍵字,也是可以的:java view plaincopy176 public class SingletonTest 177 178 private static SingletonTest instance = null; 179 180 private SingletonTest() 181 182 183 private static synchronized void syncInit() 184 if (instance = null) 185 instance = new SingletonTest(); 186 187 188 189 public static SingletonTest getInstance() 190 if (instance = null) 191 syncInit(); 192 193 return instance; 194 195 考慮性能的話,整個(gè)程序只需創(chuàng)建一次實(shí)例,所以性能也不會(huì)有什么影響。補(bǔ)充:采用影子實(shí)例的辦法為單例對(duì)象的屬性同步更新java view plaincopy196 public class SingletonTest 197 198 private static SingletonTest instance = null; 199 private Vector properties = null; 200 201 public Vector getProperties() 202 return properties; 203 204 205 private SingletonTest() 206 207 208 private static synchronized void syncInit() 209 if (instance = null) 210 instance = new SingletonTest(); 211 212 213 214 public static SingletonTest getInstance() 215 if (instance = null) 216 syncInit(); 217 218 return instance; 219 220 221 public void updateProperties() 222 SingletonTest shadow = new SingletonTest(); 223 properties = shadow.getProperties(); 224 225 通過單例模式的學(xué)習(xí)告訴我們:1、單例模式理解起來簡(jiǎn)單,但是具體實(shí)現(xiàn)起來還是有一定的難度。2、synchronized關(guān)鍵字鎖定的是對(duì)象,在用的時(shí)候,一定要在恰當(dāng)?shù)牡胤绞褂茫ㄗ⒁庑枰褂面i的對(duì)象和過程,可能有的時(shí)候并不是整個(gè)對(duì)象及整個(gè)過程都需要鎖)。到這兒,單例模式基本已經(jīng)講完了,結(jié)尾處,筆者突然想到另一個(gè)問題,就是采用類的靜態(tài)方法,實(shí)現(xiàn)單例模式的效果,也是可行的,此處二者有什么不同?首先,靜態(tài)類不能實(shí)現(xiàn)接口。(從類的角度說是可以的,但是那樣就破壞了靜態(tài)了。因?yàn)榻涌谥胁辉试S有static修飾的方法,所以即使實(shí)現(xiàn)了也是非靜態(tài)的)其次,單例可以被延遲初始化,靜態(tài)類一般在第一次加載是初始化。之所以延遲加載,是因?yàn)橛行╊惐容^龐大,所以延遲加載有助于提升性能。再次,單例類可以被繼承,他的方法可以被覆寫。但是靜態(tài)類內(nèi)部方法都是static,無法被覆寫。最后一點(diǎn),單例類比較靈活,畢竟從實(shí)現(xiàn)上只是一個(gè)普通的Java類,只要滿足單例的基本需求,你可以在里面隨心所欲的實(shí)現(xiàn)一些其它功能,但是靜態(tài)類不行。從上面這些概括中,基本可以看出二者的區(qū)別,但是,從另一方面講,我們上面最后實(shí)現(xiàn)的那個(gè)單例模式,內(nèi)部就是用一個(gè)靜態(tài)類來實(shí)現(xiàn)的,所以,二者有很大的關(guān)聯(lián),只是我們考慮問題的層面不同罷了。兩種思想的結(jié)合,才能造就出完美的解決方案,就像HashMap采用數(shù)組+鏈表來實(shí)現(xiàn)一樣,其實(shí)生活中很多事情都是這樣,單用不同的方法來處理問題,總是有優(yōu)點(diǎn)也有缺點(diǎn),最完美的方法是,結(jié)合各個(gè)方法的優(yōu)點(diǎn),才能最好的解決問題!4、建造者模式(Builder)工廠類模式提供的是創(chuàng)建單個(gè)類的模式,而建造者模式則是將各種產(chǎn)品集中起來進(jìn)行管理,用來創(chuàng)建復(fù)合對(duì)象,所謂復(fù)合對(duì)象就是指某個(gè)類具有不同的屬性,其實(shí)建造者模式就是前面抽象工廠模式和最后的Test結(jié)合起來得到的。我們看一下代碼:還和前面一樣,一個(gè)Sender接口,兩個(gè)實(shí)現(xiàn)類MailSender和SmsSender。最后,建造者類如下:java view plaincopy226 public class Builder 227 228 private List list = new ArrayList(); 229 230 public void produceMailSender(int count) 231 for(int i=0; icount; i+) 232 list.add(new MailSender(); 233 234 235 236 public void produceSmsSender(int count) 237 for(int i=0; icount; i+) 238 list.add(new SmsSender(); 239 240 241 測(cè)試類:java view plaincopy242 public class Test 243 244 public static void main(String args) 245 Builder builder = new Builder(); 246 duceMailSender(10); 247 248 從這點(diǎn)看出,建造者模式將很多功能集成到一個(gè)類里,這個(gè)類可以創(chuàng)造出比較復(fù)雜的東西。所以與工程模式的區(qū)別就是:工廠模式關(guān)注的是創(chuàng)建單個(gè)產(chǎn)品,而建造者模式則關(guān)注創(chuàng)建符合對(duì)象,多個(gè)部分。因此,是選擇工廠模式還是建造者模式,依實(shí)際情況而定。5、原型模式(Prototype)原型模式雖然是創(chuàng)建型的模式,但是與工程模式?jīng)]有關(guān)系,從名字即可看出,該模式的思想就是將一個(gè)對(duì)象作為原型,對(duì)其進(jìn)行復(fù)制、克隆,產(chǎn)生一個(gè)和原對(duì)象類似的新對(duì)象。本小結(jié)會(huì)通過對(duì)象的復(fù)制,進(jìn)行講解。在Java中,復(fù)制對(duì)象是通過clone()實(shí)現(xiàn)的,先創(chuàng)建一個(gè)原型類:java view plaincopy249 public class Prototype implements Cloneable 250 251 public Object clone() throws CloneNotSupportedException 252 Prototype proto = (Prototype) super.clone(); 253 return proto; 254 255 很簡(jiǎn)單,一個(gè)原型類,只需要實(shí)現(xiàn)Cloneable接口,覆寫clone方法,此處clone方法可以改成任意的名稱,因?yàn)镃loneable接口是個(gè)空接口,你可以任意定義實(shí)現(xiàn)類的方法名,如cloneA或者cloneB,因?yàn)榇颂幍闹攸c(diǎn)是super.clone()這句話,super.clone()調(diào)用的是Object的clone()方法,而在Object類中,clone()是native的,具體怎么實(shí)現(xiàn),我會(huì)在另一篇文章中,關(guān)于解讀Java中本地方法的調(diào)用,此處不再深究。在這兒,我將結(jié)合對(duì)象的淺復(fù)制和深復(fù)制來說一下,首先需要了解對(duì)象深、淺復(fù)制的概念:淺復(fù)制:將一個(gè)對(duì)象復(fù)制后,基本數(shù)據(jù)類型的變量都會(huì)重新創(chuàng)建,而引用類型,指向的還是原對(duì)象所指向的。深復(fù)制:將一個(gè)對(duì)象復(fù)制后,不論是基本數(shù)據(jù)類型還有引用類型,都是重新創(chuàng)建的。簡(jiǎn)單來說,就是深復(fù)制進(jìn)行了完全徹底的復(fù)制,而淺復(fù)制不徹底。此處,寫一個(gè)深淺復(fù)制的例子:java view plaincopy256 public class Prototype implements Cloneable, Serializable 257 258 private static final long serialVersionUID = 1L; 259 private String string; 260 261 private SerializableObject obj; 262 263 /* 淺復(fù)制 */ 264 public Object clone() throws CloneNotSupportedException 265 Prototype proto = (Prototype) super.clone(); 266 return proto; 267 268 269 /* 深復(fù)制 */ 270 public Object deepClone() throws IOException, ClassNotFoundException 271 272 /* 寫入當(dāng)前對(duì)象的二進(jìn)制流 */ 273 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 274 ObjectOutputStream oos = new ObjectOutputStream(bos); 275 oos.writeObject(this); 276 277 /* 讀出二進(jìn)制流產(chǎn)生的新對(duì)象 */ 278 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray(); 279 ObjectInputStream ois = new ObjectInputStream(bis); 280 return ois.readObject(); 281 282 283 public String getString() 284 return string; 285 286 287 public void setString(String string) 288 this.string = string; 289 290 291 public SerializableObject getObj() 292 return obj; 293 294 295 public void setObj(SerializableObject obj) 296 this.obj = obj; 297 298 299 300 301 class SerializableObject implements Serializable 302 private static final long serialVersionUID = 1L; 303 要實(shí)現(xiàn)深復(fù)制,需要采用流的形式讀入當(dāng)前對(duì)象的二進(jìn)制輸入,再寫出二進(jìn)制數(shù)據(jù)對(duì)應(yīng)的對(duì)象。我們接著討論設(shè)計(jì)模式,上篇文章我講完了5種創(chuàng)建型模式,這章開始,我將講下7種結(jié)構(gòu)型模式:適配器模式、裝飾模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。其中對(duì)象的適配器模式是各種模式的起源,我們看下面的圖: 適配器模式將某個(gè)類的接口轉(zhuǎn)換成客戶端期望的另一個(gè)接口表示,目的是消除由于接口不匹配所造成的類的兼容性問題。主要分為三類:類的適配器模式、對(duì)象的適配器模式、接口的適配器模式。首先,我們來看看類的適配器模式,先看類圖:核心思想就是:有一個(gè)Source類,擁有一個(gè)方法,待適配,目標(biāo)接口時(shí)Targetable,通過Adapter類,將Source的功能擴(kuò)展到Targetable里,看代碼:java view plaincopy304 public class Source 305 306 public void method1() 307 System.out.println(this is original method!); 308 309 java view plaincopy310 public interface Targetable 311 312 /* 與原類中的方法相同 */ 313 public void method1(); 314 315 /* 新類的方法 */ 316 public void method2(); 317 java view plaincopy318 public class Adapter extends Source implements Targetable 319 320 Override 321 public void method2() 322 System.out.println(this is the targetable method!); 323 324 Adapter類繼承Source類,實(shí)現(xiàn)Targetable接口,下面是測(cè)試類:java view plaincopy325 public class AdapterTest 326 327 public static void main(String args) 328 Targetable target = new Adapter(); 329 target.method1(); 330 target.method2(); 331 332 輸出:this is original method!this is the targetable method!這樣Targetable接口的實(shí)現(xiàn)類就具有了Source類的功能。對(duì)象的適配器模式基本思路和類的適配器模式相同,只是將Adapter類作修改,這次不繼承Source類,而是持有Source類的實(shí)例,以達(dá)到解決兼容性的問題。看圖: 只需要修改Adapter類的源碼即可:java view plaincopy333 public class Wrapper implements Targetable 334 335 private Source source; 336 337 public Wrapper(Source source) 338 super(); 339 this.source = source; 340 341 Override 342 public void method2() 343 System.out.println(this is the targetable method!); 344 345 346 Override 347 public void method1() 348 source.method1(); 349 350 測(cè)試類:java view plaincopy351 public class AdapterTest 352 353 public static void main(String args) 354 Source source = new Source(); 355 Targetable target = new Wrapper(source); 356 target.method1(); 357 target.method2(); 358 359 輸出與第一種一樣,只是適配的方法不同而已。第三種適配器模式是接口的適配器模式,接口的適配器是這樣的:有時(shí)我們寫的一個(gè)接口中有多個(gè)抽象方法,當(dāng)我們寫該接口的實(shí)現(xiàn)類時(shí),必須實(shí)現(xiàn)該接口的所有方法,這明顯有時(shí)比較浪費(fèi),因?yàn)椴⒉皇撬械姆椒ǘ际俏覀冃枰?,有時(shí)只需要某一些,此處為了解決這個(gè)問題,我們引入了接口的適配器模式,借助于一個(gè)抽象類,該抽象類實(shí)現(xiàn)了該接口,實(shí)現(xiàn)了所有的方法,而我們不和原始的接口打交道,只和該抽象類取得聯(lián)系,所以我們寫一個(gè)類,繼承該抽象類,重寫我們需要的方法就行??匆幌骂悎D:這個(gè)很好理解,在實(shí)際開發(fā)中,我們也常會(huì)遇到這種接口中定義了太多的方法,以致于有時(shí)我們?cè)谝恍?shí)現(xiàn)類中并不是都需要??创a:java view plaincopy360 public interface Sourceable 361 362 public void method1(); 363 public void method2(); 364 抽象類Wrapper2:java view plaincopy365 public abstract class Wrapper2 implements Sourceable 366 367 public void method1() 368 public void method2() 369 java view plaincopy370 public class SourceSub1 extends Wrapper2 371 public void method1() 372 System.out.println(the sou
溫馨提示
- 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. 人人文庫(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 室內(nèi)設(shè)計(jì)客戶信息采集指南
- 山東C類人員安全考核考試模擬題與答案(附解析)
- 兒科護(hù)理學(xué)試題及答案(附解析)
- 2025年1月安全生產(chǎn)法題庫(kù)(含答案解析)
- 煤氣化過程能源回收利用考核試卷
- 《谷歌波浪-課件概覽》講義
- 電信企業(yè)競(jìng)爭(zhēng)情報(bào)分析與商業(yè)秘密保護(hù)考核試卷
- 纜繩在醫(yī)療設(shè)備與康復(fù)訓(xùn)練中的應(yīng)用考核試卷
- 2025年P(guān)P項(xiàng)目合作計(jì)劃書
- 環(huán)境科學(xué)與工程課件
- 住建系統(tǒng)專業(yè)類法律知識(shí)考試試題及答案
- 《系統(tǒng)性紅斑狼瘡診療規(guī)范2023》解讀
- 【企業(yè)盈利能力探析的國(guó)內(nèi)外文獻(xiàn)綜述2400字】
- 牦牛養(yǎng)殖場(chǎng)布魯氏菌病凈化評(píng)估技術(shù)規(guī)范(正式稿)
- (MC)中線導(dǎo)管的臨床應(yīng)用
- DB50T 1426-2023 醫(yī)療衛(wèi)生機(jī)構(gòu)康復(fù)輔助器具適配服務(wù)規(guī)范
- 測(cè)繪生產(chǎn)成本費(fèi)用細(xì)則定額
- 課件6:環(huán)控電控柜主要部件-馬達(dá)保護(hù)器
- 七年級(jí)歷史上冊(cè) 第一單元 單元測(cè)試卷(人教版 2024年秋)
- 2024版電力服務(wù)咨詢服務(wù)合同范本
- 業(yè)務(wù)協(xié)作費(fèi)用協(xié)議書
評(píng)論
0/150
提交評(píng)論