本文說明:本文章只簡(jiǎn)單敘述設(shè)計(jì)模式,而且僅僅從理論上簡(jiǎn)單敘述,僅此而已?。?!
本文摘自網(wǎng)絡(luò),純粹復(fù)制粘貼,不喜可以出門右轉(zhuǎn)!謝謝?。?!
重要的事情說三遍:僅僅從理論上簡(jiǎn)單敘述,僅僅從理論上簡(jiǎn)單敘述,僅僅從理論上簡(jiǎn)單敘述!
設(shè)計(jì)原則:
1.單一職責(zé)原則
不要存在多于一個(gè)導(dǎo)致類變更的原因。通俗的說,即一個(gè)類只負(fù)責(zé)一項(xiàng)職責(zé)。
類T負(fù)責(zé)兩個(gè)不同的職責(zé):職責(zé)P1,職責(zé)P2。當(dāng)由于職責(zé)P1需求發(fā)生改變而需要修改類T時(shí),有可能會(huì)導(dǎo)致原本運(yùn)行正常的職責(zé)P2功能發(fā)生故障。
解決方案:遵循單一職責(zé)原則。分別建立兩個(gè)類T1、T2,使T1完成職責(zé)P1功能,T2完成職責(zé)P2功能。這樣,當(dāng)修改類T1時(shí),不會(huì)使職責(zé)P2發(fā)生故障風(fēng)險(xiǎn);同理,當(dāng)修改T2時(shí),也不會(huì)使職責(zé)P1發(fā)生故障風(fēng)險(xiǎn)。
2.里氏替換原則
如果對(duì)每一個(gè)類型為 T1的對(duì)象 o1,都有類型為 T2 的對(duì)象o2,使得以 T1定義的所有程序 P 在所有的對(duì)象 o1 都代換成 o2 時(shí),程序 P 的行為沒有發(fā)生變化,那么類型 T2 是類型 T1 的子類型。
所有引用基類的地方必須能透明地使用其子類的對(duì)象。問題由來(lái):有一功能P1,由類A完成。現(xiàn)需要將功能P1進(jìn)行擴(kuò)展,擴(kuò)展后的功能為P,其中P由原有功能P1與新功能P2組成。新功能P由類A的子類B來(lái)完成,則子類B在完成新功能P2的同時(shí),有可能會(huì)導(dǎo)致原有功能P1發(fā)生故障。
解決方案:當(dāng)使用繼承時(shí),遵循里氏替換原則。類B繼承類A時(shí),除添加新的方法完成新增功能P2外,盡量不要重寫父類A的方法,也盡量不要重載父類A的方法。
3.依賴倒置原則
高層模塊不應(yīng)該依賴低層模塊,二者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細(xì)節(jié);細(xì)節(jié)應(yīng)該依賴抽象。
類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的代碼來(lái)達(dá)成。這種場(chǎng)景下,類A一般是高層模塊,負(fù)責(zé)復(fù)雜的業(yè)務(wù)邏輯;類B和類C是低層模塊,負(fù)責(zé)基本的原子操作;假如修改類A,會(huì)給程序帶來(lái)不必要的風(fēng)險(xiǎn)。
解決方案:將類A修改為依賴接口I,類B和類C各自實(shí)現(xiàn)接口I,類A通過接口I間接與類B或者類C發(fā)生聯(lián)系,則會(huì)大大降低修改類A的幾率。
4.接口隔離原則
客戶端不應(yīng)該依賴它不需要的接口;一個(gè)類對(duì)另一個(gè)類的依賴應(yīng)該建立在最小的接口上。問題由來(lái):類A通過接口I依賴類B,類C通過接口I依賴類D,如果接口I對(duì)于類A和類B來(lái)說不是最小接口,則類B和類D必須去實(shí)現(xiàn)他們不需要的方法。
解決方案:將臃腫的接口I拆分為獨(dú)立的幾個(gè)接口,類A和類C分別與他們需要的接口建立依賴關(guān)系。也就是采用接口隔離原則。
5.迪米特法則
一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少的了解。
類與類之間的關(guān)系越密切,耦合度越大,當(dāng)一個(gè)類發(fā)生改變時(shí),對(duì)另一個(gè)類的影響也越大。
解決方案:盡量降低類與類之間的耦合。
6.開閉原則
一個(gè)軟件實(shí)體如類、模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。
在軟件的生命周期內(nèi),因?yàn)樽兓?、升?jí)和維護(hù)等原因需要對(duì)軟件原有代碼進(jìn)行修改時(shí),可能會(huì)給舊代碼中引入錯(cuò)誤,也可能會(huì)使我們不得不對(duì)整個(gè)功能進(jìn)行重構(gòu),并且需要原有代碼經(jīng)過重新測(cè)試。
解決方案:當(dāng)軟件需要變化時(shí),盡量通過擴(kuò)展軟件實(shí)體的行為來(lái)實(shí)現(xiàn)變化,而不是通過修改已有的代碼來(lái)實(shí)現(xiàn)變化。
具體的設(shè)計(jì)模式:
1.單例模式:
確保一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。單例模式注意事項(xiàng):
只能使用單例類提供的方法得到單例對(duì)象,不要使用反射,否則將會(huì)實(shí)例化一個(gè)新對(duì)象。不要做斷開單例類對(duì)象與類中靜態(tài)引用的危險(xiǎn)操作。多線程使用單例使用共享資源時(shí),注意線程安全問題。
2.工廠方法模式:
定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類,工廠方法使一個(gè)類的實(shí)例化延遲到其子類。在工廠方法模式中,核心的工廠類不再負(fù)責(zé)所有的對(duì)象的創(chuàng)建,而是將具體創(chuàng)建的工作交給子類去做。這個(gè)核心類則搖身一變,成為了一個(gè)抽象工廠角色,僅負(fù)責(zé)給出具體工廠子類必須實(shí)現(xiàn)的接口,而不接觸哪一個(gè)類應(yīng)當(dāng)被實(shí)例化這種細(xì)節(jié)。
3.抽象工廠模式
為創(chuàng)建一組相關(guān)或相互依賴的對(duì)象提供一個(gè)接口,而且無(wú)需指定他們的具體類。在以下情況下,適用于工廠方法模式:
(1) 當(dāng)一個(gè)類不知道它所必須創(chuàng)建的對(duì)象的類的時(shí)候。
(2) 當(dāng)一個(gè)類希望由它的子類來(lái)指定它所創(chuàng)建的對(duì)象的時(shí)候。
(3) 當(dāng)類將創(chuàng)建對(duì)象的職責(zé)委托給多個(gè)幫助子類中的某一個(gè),并且你希望將哪一個(gè)幫助子類是代理者這一信息局部化的時(shí)候。
4.模版方法模式
定義一個(gè)操作中算法的框架,而將一些步驟延遲到子類中,使得子類可以不改變算法的結(jié)構(gòu)即可重定義該算法中的某些特定步驟。子類可以置換掉父類的可變部分,但是子類卻不可以改變模板方法所代表的頂級(jí)邏輯。
每當(dāng)定義一個(gè)新的子類時(shí),不要按照控制流程的思路去想,而應(yīng)當(dāng)按照“責(zé)任”的思路去想。換言之,應(yīng)當(dāng)考慮哪些操作是必須置換掉的,哪些操作是可以置換掉的,以及哪些操作是不可以置換掉的。使用模板模式可以使這些責(zé)任變得清晰。
建造者模式將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。與抽象工廠的區(qū)別:在建造者模式里,有個(gè)指導(dǎo)者,由指導(dǎo)者來(lái)管理建造者,用戶是與指導(dǎo)者聯(lián)系的,指導(dǎo)者聯(lián)系建造者最后得到產(chǎn)品。即建造模式可以強(qiáng)制實(shí)行一種分步驟進(jìn)行的建造過程。
5.建造模式
是將復(fù)雜的內(nèi)部創(chuàng)建封裝在內(nèi)部,對(duì)于外部調(diào)用的人來(lái)說,只需要傳入建造者和建造工具,對(duì)于內(nèi)部是如何建造成成品的,調(diào)用者無(wú)需關(guān)心。
在Java的應(yīng)用中JavaMail使用到了該模式。
6.代理模式
為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。所謂代理,就是一個(gè)人或者機(jī)構(gòu)代表另一個(gè)人或者機(jī)構(gòu)采取行動(dòng)。在一些情況下,一個(gè)客戶不想或者不能夠直接引用一個(gè)對(duì)象,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介的作用。
7.原型模式
用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并通過拷貝這些原型創(chuàng)建新的對(duì)象。
原型模式要求對(duì)象實(shí)現(xiàn)一個(gè)可以“克隆”自身的接口,這樣就可以通過復(fù)制一個(gè)實(shí)例對(duì)象本身來(lái)創(chuàng)建一個(gè)新的實(shí)例。這樣一來(lái),通過原型實(shí)例創(chuàng)建新的對(duì)象,就不再需要關(guān)心這個(gè)實(shí)例本身的類型,只要實(shí)現(xiàn)了克隆自身的方法,就可以通過這個(gè)方法來(lái)獲取新的對(duì)象,而無(wú)須再去通過new來(lái)創(chuàng)建。在Java語(yǔ)言里深度克隆一個(gè)對(duì)象,常??梢韵仁箤?duì)象實(shí)現(xiàn)Serializable接口,然后把對(duì)象(實(shí)際上只是對(duì)象的拷貝)寫到一個(gè)流里(序列化),再?gòu)牧骼镒x回來(lái)(反序列化),便可以重建對(duì)象。
原型模式的優(yōu)點(diǎn)
原型模式允許在運(yùn)行時(shí)動(dòng)態(tài)改變具體的實(shí)現(xiàn)類型。原型模式可以在運(yùn)行期間,由客戶來(lái)注冊(cè)符合原型接口的實(shí)現(xiàn)類型,也可以動(dòng)態(tài)地改變具體的實(shí)現(xiàn)類型,看起來(lái)接口沒有任何變化,但其實(shí)運(yùn)行的已經(jīng)是另外一個(gè)類實(shí)例了。因?yàn)榭寺∫粋€(gè)原型就類似于實(shí)例化一個(gè)類。
原型模式的缺點(diǎn)
原型模式最主要的缺點(diǎn)是每一個(gè)類都必須配備一個(gè)克隆方法。配備克隆方法需要對(duì)類的功能進(jìn)行通盤考慮,這對(duì)于全新的類來(lái)說不是很難,而對(duì)于已經(jīng)有的類不一定很容易,特別是當(dāng)一個(gè)類引用不支持序列化的間接對(duì)象,或者引用含有循環(huán)結(jié)構(gòu)的時(shí)候。
8.中介者模式
用一個(gè)中介者對(duì)象封裝一系列的對(duì)象交互,中介者使各對(duì)象不需要顯示地相互作用,從而使耦合松散,而且可以獨(dú)立地改變它們之間的交互。
中介者模式的優(yōu)點(diǎn)
適當(dāng)?shù)厥褂弥薪檎吣J娇梢员苊馔骂愔g的過度耦合,使得各同事類之間可以相對(duì)獨(dú)立地使用。
使用中介者模式可以將對(duì)象間一對(duì)多的關(guān)聯(lián)轉(zhuǎn)變?yōu)橐粚?duì)一的關(guān)聯(lián),使對(duì)象間的關(guān)系易于理解和維護(hù)。
使用中介者模式可以將對(duì)象的行為和協(xié)作進(jìn)行抽象,能夠比較靈活的處理對(duì)象間的相互作用。適用場(chǎng)景
在面向?qū)ο缶幊讨?,一個(gè)類必然會(huì)與其他的類發(fā)生依賴關(guān)系,完全獨(dú)立的類是沒有意義的。一個(gè)類同時(shí)依賴多個(gè)類的情況也相當(dāng)普遍,既然存在這樣的情況,說明,一對(duì)多的依賴關(guān)系有它的合理性,適當(dāng)?shù)氖褂弥薪檎吣J娇梢允乖玖鑱y的對(duì)象關(guān)系清晰,但是如果濫用,則可能會(huì)帶來(lái)反的效果。一般來(lái)說,只有對(duì)于那種同事類之間是網(wǎng)狀結(jié)構(gòu)的關(guān)系,才會(huì)考慮使用中介者模式??梢詫⒕W(wǎng)狀結(jié)構(gòu)變?yōu)樾菭罱Y(jié)構(gòu),使同事類之間的關(guān)系變的清晰一些。
中介者模式是一種比較常用的模式,也是一種比較容易被濫用的模式。對(duì)于大多數(shù)的情況,同事類之間的關(guān)系不會(huì)復(fù)雜到混亂不堪的網(wǎng)狀結(jié)構(gòu),因此,大多數(shù)情況下,將對(duì)象間的依賴關(guān)系封裝的同事類內(nèi)部就可以的,沒有必要非引入中介者模式。濫用中介者模式,只會(huì)讓事情變的更復(fù)雜。
9.命令模式
意圖:將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或記錄日志,以及支持可撤銷的操作
動(dòng)機(jī):將”發(fā)出請(qǐng)求的對(duì)象”和”接收與執(zhí)行這些請(qǐng)求的對(duì)象”分隔開來(lái)。常見應(yīng)用:
1、工作隊(duì)列,線程池,日程安排
2、日志請(qǐng)求(系統(tǒng)恢復(fù))
要點(diǎn):
1、命令模式將發(fā)出請(qǐng)求的對(duì)象和執(zhí)行請(qǐng)求的對(duì)象解耦
2、在被解耦的兩者之間是通過命令對(duì)象進(jìn)行溝通的。命令對(duì)象封裝了接收者和一個(gè)或一組動(dòng)作
3、調(diào)用者通過調(diào)用命令對(duì)象的execute()發(fā)出請(qǐng)求,這會(huì)使得接收者的動(dòng)作被調(diào)用
4、調(diào)用者可以接受命令當(dāng)作參數(shù),甚至在運(yùn)行時(shí)動(dòng)態(tài)的進(jìn)行
5、命令可以支持撤銷,做法是實(shí)現(xiàn)一個(gè)undo()方法來(lái)回到execute()被執(zhí)行前的狀態(tài)
6、宏命令是命令的一種簡(jiǎn)單的延伸,允許調(diào)用多個(gè)命令。宏方法也可以支持撤銷
7、實(shí)際操作時(shí),很常見使用"聰明"命令對(duì)象,也就是直接實(shí)現(xiàn)了請(qǐng)求,而不是將工作委托給接受者(弊端?)
8、命令也可以用來(lái)實(shí)現(xiàn)日志和事物系統(tǒng)
10.責(zé)任鏈模式
使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免了請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有對(duì)象處理它為止。一個(gè)純的責(zé)任鏈模式要求一個(gè)具體的處理者對(duì)象只能在兩個(gè)行為中選擇一個(gè):一是承擔(dān)責(zé)任,而是把責(zé)任推給下家。不允許出現(xiàn)某一個(gè)具體處理者對(duì)象在承擔(dān)了一部分責(zé)任后又 把責(zé)任向下傳的情況。
在一個(gè)純的責(zé)任鏈模式里面,一個(gè)請(qǐng)求必須被某一個(gè)處理者對(duì)象所接收;在一個(gè)不純的責(zé)任鏈模式里面,一個(gè)請(qǐng)求可以最終不被任何接收端對(duì)象所接收。
純的責(zé)任鏈模式的實(shí)際例子很難找到,一般看到的例子均是不純的責(zé)任鏈模式的實(shí)現(xiàn)。有些人認(rèn)為不純的責(zé)任鏈根本不是責(zé)任鏈模式,這也許是有道理的。但是在實(shí)際的系統(tǒng)里,純的責(zé)任鏈很難找到。如果堅(jiān)持責(zé)任鏈不純便不是責(zé)任鏈模式,那么責(zé)任鏈模式便不會(huì)有太大意義了。
11.裝飾模式
又名包裝(Wrapper)模式,裝飾模式以對(duì)客戶端透明的方式擴(kuò)展對(duì)象的功能,是繼承關(guān)系的一個(gè)替代方案。裝飾模式與類繼承的區(qū)別:
1) ? ?裝飾模式是一種動(dòng)態(tài)行為,對(duì)已經(jīng)存在類進(jìn)行隨意組合,而類的繼承是一種靜態(tài)的行為,一個(gè)類定義成什么樣的,該類的對(duì)象便具有什么樣的功能,無(wú)法動(dòng)態(tài)的改變。
2) ? ?裝飾模式擴(kuò)展的是對(duì)象的功能,不需要增加類的數(shù)量,而類繼承擴(kuò)展是類的功能,在繼承的關(guān)系中,如果我們想增加一個(gè)對(duì)象的功能,我們只能通過繼承關(guān)系,在子類中增加兩個(gè)方法。
3) ? ?裝飾與繼承比較圖:
4) ? ?裝飾模式是在不改變?cè)愇募褪褂美^承的情況下,動(dòng)態(tài)的擴(kuò)展一個(gè)對(duì)象的功能,它是通過創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾來(lái)包裹真是的對(duì)象。
5. ? ?裝飾模式把對(duì)客戶端的調(diào)用委派給被裝飾的類,裝飾模式的關(guān)鍵在于這種擴(kuò)展完全透明的。
12.策略模式
定義一組算法,將每個(gè)算法都封裝起來(lái),并且使他們之間可以互換。
策略模式的好處在于你可以動(dòng)態(tài)的改變對(duì)象的行為。策略模式屬于對(duì)象行為型模式,主要針對(duì)一組算法,將每一個(gè)算法封裝到具有共同接口的獨(dú)立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響
到客戶端的情況下發(fā)生變化。通常,策略模式適用于當(dāng)一個(gè)應(yīng)用程序需要實(shí)現(xiàn)一種特定的服務(wù)或者功能,而且該程序有多種實(shí)現(xiàn)方式時(shí)使用。
13.適配器模式
基于現(xiàn)有類所提供的服務(wù),向客戶提供接口,以滿足客戶的期望。
適配器模式的用意是要改變?cè)吹慕涌?,以便于目?biāo)接口相容。缺省適配的用意稍有不同,它是為了方便建立一個(gè)不平庸的適配器類而提供的一種平庸實(shí)現(xiàn)。適配器模式的優(yōu)點(diǎn)
更好的復(fù)用性
系統(tǒng)需要使用現(xiàn)有的類,而此類的接口不符合系統(tǒng)的需要。那么通過適配器模式就可以讓這些功能得到更好的復(fù)用。
更好的擴(kuò)展性
在實(shí)現(xiàn)適配器功能的時(shí)候,可以調(diào)用自己開發(fā)的功能,從而自然地?cái)U(kuò)展系統(tǒng)的功能。
適配器模式的缺點(diǎn)
過多的使用適配器,會(huì)讓系統(tǒng)非常零亂,不易整體進(jìn)行把握。比如,明明看到調(diào)用的是A接口,其實(shí)內(nèi)部被適配成了B接口的實(shí)現(xiàn),一個(gè)系統(tǒng)如果太多出現(xiàn)這種情況,無(wú)異于一場(chǎng)災(zāi)難。因此如果不是很有必要,可以不使用適配器,而是直接對(duì)系統(tǒng)進(jìn)行重構(gòu)。
14.迭代器模式
提供一種方法訪問一個(gè)容器對(duì)象中各個(gè)元素,而又不暴露該對(duì)象的內(nèi)部細(xì)節(jié)。在jdk中,與迭代器相關(guān)的接口有兩個(gè):Iterator 與 Iterable
Iterator:迭代器,Iterator及其子類通常是迭代器本身的結(jié)構(gòu)與方法;
Iterable:可迭代的,那些想用到迭代器功能的其它類,如AbstractList HashMap等,需要實(shí)現(xiàn)該接口。
15.組合模式
將對(duì)象組合成樹形結(jié)構(gòu)以表示‘部分-整體’的層次結(jié)構(gòu)。組合模式使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。
對(duì)象通過實(shí)現(xiàn)(繼承)統(tǒng)一的接口(抽象類),調(diào)用者對(duì)單一對(duì)象和組合對(duì)象的操作具有一致性。通過實(shí)現(xiàn)組合模式,調(diào)用者對(duì)組合對(duì)象的操作與對(duì)單一對(duì)象的操作具有一致性。調(diào)用者不用關(guān)心這是組合對(duì)象還是文件,也不用關(guān)心組合對(duì)象內(nèi)部的具體結(jié)構(gòu),就可以調(diào)用相關(guān)方法,實(shí)現(xiàn)功能。
16.觀察者模式
定義對(duì)象間一種一對(duì)多的依賴關(guān)系,使得當(dāng)每一個(gè)對(duì)象改變狀態(tài),則所有依賴于它的對(duì)象都會(huì)得到通知并自動(dòng)更新。
觀察者模式定義了一種一對(duì)多的依賴關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽某一個(gè)主題對(duì)象。這個(gè)主題對(duì)象在狀態(tài)上發(fā)生變化時(shí),會(huì)通知所有觀察者對(duì)象,使它們能夠自動(dòng)更新自己。在JAVA語(yǔ)言的java.util庫(kù)里面,提供了一個(gè)Observable類以及一個(gè)Observer接口,構(gòu)成JAVA語(yǔ)言對(duì)觀察者模式的支持。
17.門面模式
外部與一個(gè)子系統(tǒng)的通信必須通過一個(gè)統(tǒng)一的門面對(duì)象進(jìn)行。門面模式的優(yōu)點(diǎn):
● 松散耦合
門面模式松散了客戶端與子系統(tǒng)的耦合關(guān)系,讓子系統(tǒng)內(nèi)部的模塊能更容易擴(kuò)展和維護(hù)。
● 簡(jiǎn)單易用
門面模式讓子系統(tǒng)更加易用,客戶端不再需要了解子系統(tǒng)內(nèi)部的實(shí)現(xiàn),也不需要跟眾多子系統(tǒng)內(nèi)部的模塊進(jìn)行交互,只需要跟門面類交互就可以了。
● 更好的劃分訪問層次
通過合理使用Facade,可以幫助我們更好地劃分訪問的層次。有些方法是對(duì)系統(tǒng)外的,有些方法是系統(tǒng)內(nèi)部使用的。把需要暴露給外部的功能集中到門面中,這樣既方便客戶端使用,也很好地隱藏了內(nèi)部的細(xì)節(jié)。
18.備忘錄模式
在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。這樣就可以將該對(duì)象恢復(fù)到原先保存的狀態(tài)。備忘錄對(duì)象是一個(gè)用來(lái)存儲(chǔ)另外一個(gè)對(duì)象內(nèi)部狀態(tài)的快照的對(duì)象。備忘錄模式的用意是在不破壞封裝的條件下,將一個(gè)對(duì)象的狀態(tài)捕捉(Capture)住,并外部化,存儲(chǔ)起來(lái),從而可以在將來(lái)合適的時(shí)候把這個(gè)對(duì)象還原到存儲(chǔ)起來(lái)的狀態(tài)。備忘錄模式常常與命令模式和迭代子模式一同使用。
19.訪問者模式
封裝某些作用于某種數(shù)據(jù)結(jié)構(gòu)中各元素的操作,它可以在不改變數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作。
訪問者模式是對(duì)象的行為模式。訪問者模式的目的是封裝一些施加于某種數(shù)據(jù)結(jié)構(gòu)元素之上的操作。一旦這些操作需要修改的話,接受這個(gè)操作的數(shù)據(jù)結(jié)構(gòu)則可以保持不變。
訪問者模式的優(yōu)點(diǎn)
a好的擴(kuò)展性.能夠在不修改對(duì)象結(jié)構(gòu)中的元素的情況下,為對(duì)象結(jié)構(gòu)中的元素添加新的功能。
b好的復(fù)用性.可以通過訪問者來(lái)定義整個(gè)對(duì)象結(jié)構(gòu)通用的功能,從而提高復(fù)用程度。
c分離無(wú)關(guān)行為.可以通過訪問者來(lái)分離無(wú)關(guān)的行為,把相關(guān)的行為封裝在一起,構(gòu)成一個(gè)訪問者,這樣每一個(gè)訪問者的功能都比較單一。
訪問者模式的缺點(diǎn)
a對(duì)象結(jié)構(gòu)變化很困難.不適用于對(duì)象結(jié)構(gòu)中的類經(jīng)常變化的情況,因?yàn)閷?duì)象結(jié)構(gòu)發(fā)生了改變,訪問者的接口和訪問者的實(shí)現(xiàn)都要發(fā)生相應(yīng)的改變,代價(jià)太高。
b破壞封裝.訪問者模式通常需要對(duì)象結(jié)構(gòu)開放內(nèi)部數(shù)據(jù)給訪問者和ObjectStructrue,這破壞了對(duì)象的封裝性。
20.狀態(tài)模式.
當(dāng)一個(gè)對(duì)象的內(nèi)在狀態(tài)改變時(shí)允許改變其行為,這個(gè)對(duì)象看起來(lái)像是改變了其類。
狀態(tài)模式.允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變的時(shí)候改變其行為。這個(gè)對(duì)象看上去就像是改變了它的類一樣。
21.解釋器模式
給定一種語(yǔ)言,定義他的文法的一種表示,并定義一個(gè)解釋器,該解釋器使用該表示來(lái)解釋語(yǔ)言中句子。
22.享元模式.
復(fù)用我們內(nèi)存中已存在的對(duì)象,降低系統(tǒng)創(chuàng)建對(duì)象實(shí)例的性能消耗。
Flyweight在拳擊比賽中指最輕量級(jí),即“蠅量級(jí)”或“雨量級(jí)”,這里選擇使用“享元模式”的意譯,是因?yàn)檫@樣更能反映模式的用意。享元模式是對(duì)象的結(jié)構(gòu)模式。享元模式以共享的方式高效地支持大量的細(xì)粒度對(duì)象。享元模式采用一個(gè)共享來(lái)避免大量擁有相同內(nèi)容對(duì)象的開銷。這種開銷最常見、最直觀的就是內(nèi)存的損耗。享元對(duì)象能做到共享的關(guān)鍵是區(qū)分內(nèi)蘊(yùn)狀態(tài)(Internal State)和外蘊(yùn)狀態(tài)(External State)。
23.橋梁模式
將抽象和實(shí)現(xiàn)解耦,使得兩者可以獨(dú)立地變化。
橋梁模式的用意是“將抽象化(Abstraction)與實(shí)現(xiàn)化(Implementation)脫耦,使得二者可以獨(dú)立地變化”。橋梁模式在Java應(yīng)用中的一個(gè)非常典型的例子就是JDBC驅(qū)動(dòng)器。JDBC為所有的關(guān)系型數(shù)據(jù)庫(kù)提供一個(gè)通用的界面。一個(gè)應(yīng)用系統(tǒng)動(dòng)態(tài)地選擇一個(gè)合適的驅(qū)動(dòng)器,然后通過驅(qū)動(dòng)器向數(shù)據(jù)庫(kù)引擎發(fā)出指令。這個(gè)過程就是將抽象角色的行為委派給實(shí)現(xiàn)角色的過程。