簡介
項目開發(fā)中發(fā)現(xiàn)問題租谈、解決問題這個過程中會出現(xiàn)很多問題,比如重復(fù)出現(xiàn)捆愁、某個問題的遺留割去,這些問題的本質(zhì)就是設(shè)計模式。今天記錄設(shè)計模式的知識點昼丑。
在Java以及其他的面向?qū)ο笤O(shè)計模式中呻逆,類與類之間主要有6種關(guān)系,他們分別是:依賴菩帝、關(guān)聯(lián)咖城、聚合、組合呼奢、繼承宜雀、實現(xiàn)。它們的耦合度依次增強握础。
依賴關(guān)系:
對于兩個相對獨立的對象辐董,當一個對象負責(zé)構(gòu)造另一個對象的實例,或者依賴另一個對象的服務(wù)時弓候,這兩個對象之間主要體現(xiàn)為依賴關(guān)系。
關(guān)聯(lián)關(guān)系:
分為單向關(guān)聯(lián)和雙向關(guān)聯(lián)他匪。在java中菇存,單向關(guān)聯(lián)表現(xiàn)為:類A當中使用了類B,其中類B是作為類A的成員變量邦蜜。雙向關(guān)聯(lián)表現(xiàn)為:類A當中使用了類B作為成員變量依鸥;同時類B中也使用了類A作為成員變量。
聚合關(guān)系:
是關(guān)聯(lián)關(guān)系的一種悼沈,耦合度強于關(guān)聯(lián)贱迟,他們的代碼表現(xiàn)是相同的,僅僅是在語義上有所區(qū)別:關(guān)聯(lián)關(guān)系的對象間是相互獨立的絮供,而聚合關(guān)系的對象之間存在著包容關(guān)系衣吠,他們之間是“整體-個體”的相互關(guān)系。
組合關(guān)系:
是一種耦合度更強的關(guān)聯(lián)關(guān)系壤靶。存在組合關(guān)系的類表示“整體-部分”的關(guān)聯(lián)關(guān)系缚俏,“整體”負責(zé)“部分”的生命周期,他們之間是共生共死的;并且“部分”單獨存在時沒有任何意義忧换。
繼承:
表示類與類(或者接口與接口)之間的父子關(guān)系恬惯。
實現(xiàn):
表示一個類實現(xiàn)一個或多個接口的方法。
設(shè)計原則
要點定義描述
單一職責(zé)原則不要存在多于一個導(dǎo)致類變更的原因亚茬。通俗的說酪耳,即一個類只負責(zé)一項職責(zé)。問題由來:類T負責(zé)兩個不同的職責(zé):職責(zé)P1刹缝,職責(zé)P2碗暗。當由于職責(zé)P1需求發(fā)生改變而需要修改類T時,有可能會導(dǎo)致原本運行正常的職責(zé)P2功能發(fā)生故障赞草。
解決方案:遵循單一職責(zé)原則讹堤。分別建立兩個類T1、T2厨疙,使T1完成職責(zé)P1功能洲守,T2完成職責(zé)P2功能。這樣沾凄,當修改類T1時梗醇,不會使職責(zé)P2發(fā)生故障風(fēng)險;同理撒蟀,當修改T2時叙谨,也不會使職責(zé)P1發(fā)生故障風(fēng)險。
里氏替換原則定義1:如果對每一個類型為 T1的對象 o1保屯,都有類型為 T2 的對象o2手负,使得以 T1定義的所有程序 P 在所有的對象 o1 都代換成 o2 時,程序 P 的行為沒有發(fā)生變化姑尺,那么類型 T2 是類型 T1 的子類型竟终。
定義2:所有引用基類的地方必須能透明地使用其子類的對象。問題由來:有一功能P1切蟋,由類A完成⊥炒罚現(xiàn)需要將功能P1進行擴展,擴展后的功能為P柄粹,其中P由原有功能P1與新功能P2組成喘鸟。新功能P由類A的子類B來完成,則子類B在完成新功能P2的同時驻右,有可能會導(dǎo)致原有功能P1發(fā)生故障什黑。
解決方案:當使用繼承時,遵循里氏替換原則堪夭。類B繼承類A時兑凿,除添加新的方法完成新增功能P2外凯力,盡量不要重寫父類A的方法,也盡量不要重載父類A的方法礼华。
依賴倒置原則高層模塊不應(yīng)該依賴低層模塊咐鹤,二者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細節(jié)圣絮;細節(jié)應(yīng)該依賴抽象祈惶。問題由來:類A直接依賴類B,假如要將類A改為依賴類C扮匠,則必須通過修改類A的代碼來達成捧请。這種場景下,類A一般是高層模塊棒搜,負責(zé)復(fù)雜的業(yè)務(wù)邏輯疹蛉;類B和類C是低層模塊,負責(zé)基本的原子操作力麸;假如修改類A可款,會給程序帶來不必要的風(fēng)險。
解決方案:將類A修改為依賴接口I克蚂,類B和類C各自實現(xiàn)接口I闺鲸,類A通過接口I間接與類B或者類C發(fā)生聯(lián)系,則會大大降低修改類A的幾率埃叭。
接口隔離原則客戶端不應(yīng)該依賴它不需要的接口摸恍;一個類對另一個類的依賴應(yīng)該建立在最小的接口上。問題由來:類A通過接口I依賴類B赤屋,類C通過接口I依賴類D立镶,如果接口I對于類A和類B來說不是最小接口,則類B和類D必須去實現(xiàn)他們不需要的方法类早。
解決方案:將臃腫的接口I拆分為獨立的幾個接口媚媒,類A和類C分別與他們需要的接口建立依賴關(guān)系。也就是采用接口隔離原則莺奔。
迪米特法則一個對象應(yīng)該對其他對象保持最少的了解欣范。問題由來:類與類之間的關(guān)系越密切变泄,耦合度越大令哟,當一個類發(fā)生改變時,對另一個類的影響也越大妨蛹。
解決方案:盡量降低類與類之間的耦合屏富。
開閉原則一個軟件實體如類、模塊和函數(shù)應(yīng)該對擴展開放蛙卤,對修改關(guān)閉狠半。問題由來:在軟件的生命周期內(nèi)噩死,因為變化、升級和維護等原因需要對軟件原有代碼進行修改時神年,可能會給舊代碼中引入錯誤已维,也可能會使我們不得不對整個功能進行重構(gòu),并且需要原有代碼經(jīng)過重新測試已日。
解決方案:當軟件需要變化時垛耳,盡量通過擴展軟件實體的行為來實現(xiàn)變化,而不是通過修改已有的代碼來實現(xiàn)變化飘千。
設(shè)計模式
要點定義描述
單例模式確保一個類只有一個實例堂鲜,而且自行實例化并向整個系統(tǒng)提供這個實例。單例模式注意事項:
只能使用單例類提供的方法得到單例對象护奈,不要使用反射缔莲,否則將會實例化一個新對象。不要做斷開單例類對象與類中靜態(tài)引用的危險操作霉旗。多線程使用單例使用共享資源時痴奏,注意線程安全問題。
工廠方法模式定義一個用于創(chuàng)建對象的接口奖慌,讓子類決定實例化哪一個類抛虫,工廠方法使一個類的實例化延遲到其子類。在工廠方法模式中简僧,核心的工廠類不再負責(zé)所有的對象的創(chuàng)建锅锨,而是將具體創(chuàng)建的工作交給子類去做。這個核心類則搖身一變编振,成為了一個抽象工廠角色届案,僅負責(zé)給出具體工廠子類必須實現(xiàn)的接口,而不接觸哪一個類應(yīng)當被實例化這種細節(jié)啦逆。
抽象工廠模式為創(chuàng)建一組相關(guān)或相互依賴的對象提供一個接口伞矩,而且無需指定他們的具體類。在以下情況下夏志,適用于工廠方法模式:
(1) 當一個類不知道它所必須創(chuàng)建的對象的類的時候乃坤。
(2) 當一個類希望由它的子類來指定它所創(chuàng)建的對象的時候。
(3) 當類將創(chuàng)建對象的職責(zé)委托給多個幫助子類中的某一個沟蔑,并且你希望將哪一個幫助子類是代理者這一信息局部化的時候湿诊。
模版方法模式定義一個操作中算法的框架,而將一些步驟延遲到子類中瘦材,使得子類可以不改變算法的結(jié)構(gòu)即可重定義該算法中的某些特定步驟厅须。子類可以置換掉父類的可變部分,但是子類卻不可以改變模板方法所代表的頂級邏輯食棕。
每當定義一個新的子類時朗和,不要按照控制流程的思路去想错沽,而應(yīng)當按照“責(zé)任”的思路去想。換言之眶拉,應(yīng)當考慮哪些操作是必須置換掉的千埃,哪些操作是可以置換掉的,以及哪些操作是不可以置換掉的忆植。使用模板模式可以使這些責(zé)任變得清晰镰禾。
建造者模式將一個復(fù)雜對象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示唱逢。與抽象工廠的區(qū)別:在建造者模式里吴侦,有個指導(dǎo)者,由指導(dǎo)者來管理建造者坞古,用戶是與指導(dǎo)者聯(lián)系的备韧,指導(dǎo)者聯(lián)系建造者最后得到產(chǎn)品。即建造模式可以強制實行一種分步驟進行的建造過程痪枫。
建造模式是將復(fù)雜的內(nèi)部創(chuàng)建封裝在內(nèi)部织堂,對于外部調(diào)用的人來說,只需要傳入建造者和建造工具奶陈,對于內(nèi)部是如何建造成成品的易阳,調(diào)用者無需關(guān)心。
在Java的應(yīng)用中JavaMail使用到了該模式吃粒。
代理模式為其他對象提供一種代理以控制對這個對象的訪問潦俺。所謂代理,就是一個人或者機構(gòu)代表另一個人或者機構(gòu)采取行動徐勃。在一些情況下事示,一個客戶不想或者不能夠直接引用一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用僻肖。
原型模式用原型實例指定創(chuàng)建對象的種類肖爵,并通過拷貝這些原型創(chuàng)建新的對象。
原型模式要求對象實現(xiàn)一個可以“克隆”自身的接口臀脏,這樣就可以通過復(fù)制一個實例對象本身來創(chuàng)建一個新的實例劝堪。這樣一來,通過原型實例創(chuàng)建新的對象揉稚,就不再需要關(guān)心這個實例本身的類型秒啦,只要實現(xiàn)了克隆自身的方法,就可以通過這個方法來獲取新的對象窃植,而無須再去通過new來創(chuàng)建帝蒿。在Java語言里深度克隆一個對象荐糜,常诚锪可以先使對象實現(xiàn)Serializable接口葛超,然后把對象(實際上只是對象的拷貝)寫到一個流里(序列化),再從流里讀回來(反序列化)延塑,便可以重建對象绣张。
原型模式的優(yōu)點
原型模式允許在運行時動態(tài)改變具體的實現(xiàn)類型。原型模式可以在運行期間关带,由客戶來注冊符合原型接口的實現(xiàn)類型侥涵,也可以動態(tài)地改變具體的實現(xiàn)類型,看起來接口沒有任何變化宋雏,但其實運行的已經(jīng)是另外一個類實例了芜飘。因為克隆一個原型就類似于實例化一個類。
原型模式的缺點
原型模式最主要的缺點是每一個類都必須配備一個克隆方法磨总。配備克隆方法需要對類的功能進行通盤考慮嗦明,這對于全新的類來說不是很難,而對于已經(jīng)有的類不一定很容易蚪燕,特別是當一個類引用不支持序列化的間接對象娶牌,或者引用含有循環(huán)結(jié)構(gòu)的時候。
中介者模式用一個中介者對象封裝一系列的對象交互馆纳,中介者使各對象不需要顯示地相互作用诗良,從而使耦合松散,而且可以獨立地改變它們之間的交互鲁驶。
中介者模式的優(yōu)點
適當?shù)厥褂弥薪檎吣J娇梢员苊馔骂愔g的過度耦合鉴裹,使得各同事類之間可以相對獨立地使用。
使用中介者模式可以將對象間一對多的關(guān)聯(lián)轉(zhuǎn)變?yōu)橐粚σ坏年P(guān)聯(lián)钥弯,使對象間的關(guān)系易于理解和維護壹罚。
使用中介者模式可以將對象的行為和協(xié)作進行抽象,能夠比較靈活的處理對象間的相互作用寿羞。適用場景
在面向?qū)ο缶幊讨胁荩粋€類必然會與其他的類發(fā)生依賴關(guān)系,完全獨立的類是沒有意義的绪穆。一個類同時依賴多個類的情況也相當普遍辨泳,既然存在這樣的情況,說明玖院,一對多的依賴關(guān)系有它的合理性菠红,適當?shù)氖褂弥薪檎吣J娇梢允乖玖鑱y的對象關(guān)系清晰,但是如果濫用难菌,則可能會帶來反的效果试溯。一般來說,只有對于那種同事類之間是網(wǎng)狀結(jié)構(gòu)的關(guān)系郊酒,才會考慮使用中介者模式遇绞〖ぃ可以將網(wǎng)狀結(jié)構(gòu)變?yōu)樾菭罱Y(jié)構(gòu),使同事類之間的關(guān)系變的清晰一些摹闽。
中介者模式是一種比較常用的模式蹄咖,也是一種比較容易被濫用的模式。對于大多數(shù)的情況付鹿,同事類之間的關(guān)系不會復(fù)雜到混亂不堪的網(wǎng)狀結(jié)構(gòu)澜汤,因此,大多數(shù)情況下舵匾,將對象間的依賴關(guān)系封裝的同事類內(nèi)部就可以的俊抵,沒有必要非引入中介者模式。濫用中介者模式坐梯,只會讓事情變的更復(fù)雜务蝠。
命令模式意圖:將一個請求封裝為一個對象,從而可用不同的請求對客戶進行參數(shù)化烛缔;對請求排隊或記錄日志馏段,以及支持可撤銷的操作
動機:將”發(fā)出請求的對象”和”接收與執(zhí)行這些請求的對象”分隔開來。常見應(yīng)用:
1践瓷、工作隊列院喜,線程池,日程安排
2晕翠、日志請求(系統(tǒng)恢復(fù))
要點:
1喷舀、命令模式將發(fā)出請求的對象和執(zhí)行請求的對象解耦
2、在被解耦的兩者之間是通過命令對象進行溝通的淋肾。命令對象封裝了接收者和一個或一組動作
3硫麻、調(diào)用者通過調(diào)用命令對象的execute()發(fā)出請求,這會使得接收者的動作被調(diào)用
4樊卓、調(diào)用者可以接受命令當作參數(shù)拿愧,甚至在運行時動態(tài)的進行
5、命令可以支持撤銷碌尔,做法是實現(xiàn)一個undo()方法來回到execute()被執(zhí)行前的狀態(tài)
6浇辜、宏命令是命令的一種簡單的延伸,允許調(diào)用多個命令唾戚。宏方法也可以支持撤銷
7柳洋、實際操作時,很常見使用"聰明"命令對象叹坦,也就是直接實現(xiàn)了請求熊镣,而不是將工作委托給接受者(弊端?)
8、命令也可以用來實現(xiàn)日志和事物系統(tǒng)
責(zé)任鏈模式使多個對象都有機會處理請求绪囱,從而避免了請求的發(fā)送者和接收者之間的耦合關(guān)系测蹲。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求毕箍,直到有對象處理它為止。一個純的責(zé)任鏈模式要求一個具體的處理者對象只能在兩個行為中選擇一個:一是承擔(dān)責(zé)任道盏,而是把責(zé)任推給下家而柑。不允許出現(xiàn)某一個具體處理者對象在承擔(dān)了一部分責(zé)任后又 把責(zé)任向下傳的情況。
在一個純的責(zé)任鏈模式里面荷逞,一個請求必須被某一個處理者對象所接收媒咳;在一個不純的責(zé)任鏈模式里面,一個請求可以最終不被任何接收端對象所接收种远。
純的責(zé)任鏈模式的實際例子很難找到涩澡,一般看到的例子均是不純的責(zé)任鏈模式的實現(xiàn)。有些人認為不純的責(zé)任鏈根本不是責(zé)任鏈模式坠敷,這也許是有道理的妙同。但是在實際的系統(tǒng)里,純的責(zé)任鏈很難找到膝迎。如果堅持責(zé)任鏈不純便不是責(zé)任鏈模式粥帚,那么責(zé)任鏈模式便不會有太大意義了。
裝飾模式又名包裝(Wrapper)模式限次,裝飾模式以對客戶端透明的方式擴展對象的功能芒涡,是繼承關(guān)系的一個替代方案。裝飾模式與類繼承的區(qū)別:
1) ? ?裝飾模式是一種動態(tài)行為卖漫,對已經(jīng)存在類進行隨意組合费尽,而類的繼承是一種靜態(tài)的行為,一個類定義成什么樣的羊始,該類的對象便具有什么樣的功能旱幼,無法動態(tài)的改變。
2) ? ?裝飾模式擴展的是對象的功能突委,不需要增加類的數(shù)量速警,而類繼承擴展是類的功能,在繼承的關(guān)系中鸯两,如果我們想增加一個對象的功能闷旧,我們只能通過繼承關(guān)系,在子類中增加兩個方法钧唐。
3) ? ?裝飾與繼承比較圖:
4) ? ?裝飾模式是在不改變原類文件和使用繼承的情況下忙灼,動態(tài)的擴展一個對象的功能,它是通過創(chuàng)建一個包裝對象,也就是裝飾來包裹真是的對象该园。
5. ? ?裝飾模式把對客戶端的調(diào)用委派給被裝飾的類酸舍,裝飾模式的關(guān)鍵在于這種擴展完全透明的。
策略模式定義一組算法里初,將每個算法都封裝起來啃勉,并且使他們之間可以互換。
策略模式的好處在于你可以動態(tài)的改變對象的行為双妨。策略模式屬于對象行為型模式淮阐,主要針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中刁品,從而使得它們可以相互替換泣特。策略模式使得算法可以在不影響 到客戶端的情況下發(fā)生變化。通常挑随,策略模式適用于當一個應(yīng)用程序需要實現(xiàn)一種特定的服務(wù)或者功能状您,而且該程序有多種實現(xiàn)方式時使用。
適配器模式基于現(xiàn)有類所提供的服務(wù)兜挨,向客戶提供接口膏孟,以滿足客戶的期望。
適配器模式的用意是要改變源的接口拌汇,以便于目標接口相容骆莹。缺省適配的用意稍有不同,它是為了方便建立一個不平庸的適配器類而提供的一種平庸實現(xiàn)担猛。適配器模式的優(yōu)點
更好的復(fù)用性
系統(tǒng)需要使用現(xiàn)有的類幕垦,而此類的接口不符合系統(tǒng)的需要。那么通過適配器模式就可以讓這些功能得到更好的復(fù)用傅联。
更好的擴展性
在實現(xiàn)適配器功能的時候先改,可以調(diào)用自己開發(fā)的功能,從而自然地擴展系統(tǒng)的功能蒸走。
適配器模式的缺點
過多的使用適配器仇奶,會讓系統(tǒng)非常零亂,不易整體進行把握比驻。比如该溯,明明看到調(diào)用的是A接口,其實內(nèi)部被適配成了B接口的實現(xiàn)别惦,一個系統(tǒng)如果太多出現(xiàn)這種情況狈茉,無異于一場災(zāi)難。因此如果不是很有必要掸掸,可以不使用適配器氯庆,而是直接對系統(tǒng)進行重構(gòu)蹭秋。
迭代器模式提供一種方法訪問一個容器對象中各個元素,而又不暴露該對象的內(nèi)部細節(jié)堤撵。在jdk中,與迭代器相關(guān)的接口有兩個:Iterator 與 Iterable
Iterator:迭代器仁讨,Iterator及其子類通常是迭代器本身的結(jié)構(gòu)與方法;
Iterable:可迭代的实昨,那些想用到迭代器功能的其它類洞豁,如AbstractList HashMap等,需要實現(xiàn)該接口荒给。
組合模式將對象組合成樹形結(jié)構(gòu)以表示‘部分-整體’的層次結(jié)構(gòu)丈挟。組合模式使得用戶對單個對象和組合對象的使用具有一致性。
對象通過實現(xiàn)(繼承)統(tǒng)一的接口(抽象類)锐墙,調(diào)用者對單一對象和組合對象的操作具有一致性礁哄。通過實現(xiàn)組合模式长酗,調(diào)用者對組合對象的操作與對單一對象的操作具有一致性溪北。調(diào)用者不用關(guān)心這是組合對象還是文件,也不用關(guān)心組合對象內(nèi)部的具體結(jié)構(gòu)夺脾,就可以調(diào)用相關(guān)方法之拨,實現(xiàn)功能。
觀察者模式定義對象間一種一對多的依賴關(guān)系咧叭,使得當每一個對象改變狀態(tài)蚀乔,則所有依賴于它的對象都會得到通知并自動更新。
觀察者模式定義了一種一對多的依賴關(guān)系菲茬,讓多個觀察者對象同時監(jiān)聽某一個主題對象吉挣。這個主題對象在狀態(tài)上發(fā)生變化時,會通知所有觀察者對象婉弹,使它們能夠自動更新自己睬魂。在JAVA語言的java.util庫里面,提供了一個Observable類以及一個Observer接口镀赌,構(gòu)成JAVA語言對觀察者模式的支持氯哮。
門面模式外部與一個子系統(tǒng)的通信必須通過一個統(tǒng)一的門面對象進行。門面模式的優(yōu)點:
● 松散耦合
門面模式松散了客戶端與子系統(tǒng)的耦合關(guān)系商佛,讓子系統(tǒng)內(nèi)部的模塊能更容易擴展和維護喉钢。
● 簡單易用
門面模式讓子系統(tǒng)更加易用,客戶端不再需要了解子系統(tǒng)內(nèi)部的實現(xiàn)良姆,也不需要跟眾多子系統(tǒng)內(nèi)部的模塊進行交互肠虽,只需要跟門面類交互就可以了。
● 更好的劃分訪問層次
通過合理使用Facade玛追,可以幫助我們更好地劃分訪問的層次舔痕。有些方法是對系統(tǒng)外的,有些方法是系統(tǒng)內(nèi)部使用的。把需要暴露給外部的功能集中到門面中伯复,這樣既方便客戶端使用慨代,也很好地隱藏了內(nèi)部的細節(jié)。
備忘錄模式在不破壞封裝性的前提下啸如,捕獲一個對象的內(nèi)部狀態(tài)侍匙,并在該對象之外保存這個狀態(tài)。這樣就可以將該對象恢復(fù)到原先保存的狀態(tài)叮雳。備忘錄對象是一個用來存儲另外一個對象內(nèi)部狀態(tài)的快照的對象想暗。備忘錄模式的用意是在不破壞封裝的條件下,將一個對象的狀態(tài)捕捉(Capture)住帘不,并外部化说莫,存儲起來,從而可以在將來合適的時候把這個對象還原到存儲起來的狀態(tài)寞焙。備忘錄模式常常與命令模式和迭代子模式一同使用储狭。
訪問者模式封裝某些作用于某種數(shù)據(jù)結(jié)構(gòu)中各元素的操作,它可以在不改變數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作捣郊。
訪問者模式是對象的行為模式辽狈。訪問者模式的目的是封裝一些施加于某種數(shù)據(jù)結(jié)構(gòu)元素之上的操作。一旦這些操作需要修改的話呛牲,接受這個操作的數(shù)據(jù)結(jié)構(gòu)則可以保持不變刮萌。訪問者模式的優(yōu)點
好的擴展性
能夠在不修改對象結(jié)構(gòu)中的元素的情況下,為對象結(jié)構(gòu)中的元素添加新的功能娘扩。
好的復(fù)用性
可以通過訪問者來定義整個對象結(jié)構(gòu)通用的功能着茸,從而提高復(fù)用程度。
分離無關(guān)行為
可以通過訪問者來分離無關(guān)的行為琐旁,把相關(guān)的行為封裝在一起涮阔,構(gòu)成一個訪問者,這樣每一個訪問者的功能都比較單一旋膳。
訪問者模式的缺點
對象結(jié)構(gòu)變化很困難
不適用于對象結(jié)構(gòu)中的類經(jīng)常變化的情況澎语,因為對象結(jié)構(gòu)發(fā)生了改變,訪問者的接口和訪問者的實現(xiàn)都要發(fā)生相應(yīng)的改變验懊,代價太高擅羞。
破壞封裝
訪問者模式通常需要對象結(jié)構(gòu)開放內(nèi)部數(shù)據(jù)給訪問者和ObjectStructrue,這破壞了對象的封裝性义图。
狀態(tài)模式當一個對象的內(nèi)在狀態(tài)改變時允許改變其行為减俏,這個對象看起來像是改變了其類。
狀態(tài)模式允許一個對象在其內(nèi)部狀態(tài)改變的時候改變其行為碱工。這個對象看上去就像是改變了它的類一樣娃承。
解釋器模式給定一種語言奏夫,定義他的文法的一種表示,并定義一個解釋器历筝,該解釋器使用該表示來解釋語言中句子酗昼。
享元模式復(fù)用我們內(nèi)存中已存在的對象,降低系統(tǒng)創(chuàng)建對象實例的性能消耗梳猪。
Flyweight在拳擊比賽中指最輕量級麻削,即“蠅量級”或“雨量級”,這里選擇使用“享元模式”的意譯春弥,是因為這樣更能反映模式的用意呛哟。享元模式是對象的結(jié)構(gòu)模式。享元模式以共享的方式高效地支持大量的細粒度對象匿沛。享元模式采用一個共享來避免大量擁有相同內(nèi)容對象的開銷扫责。這種開銷最常見、最直觀的就是內(nèi)存的損耗逃呼。享元對象能做到共享的關(guān)鍵是區(qū)分內(nèi)蘊狀態(tài)(Internal State)和外蘊狀態(tài)(External State)鳖孤。
橋梁模式將抽象和實現(xiàn)解耦,使得兩者可以獨立地變化蜘渣。
橋梁模式的用意是“將抽象化(Abstraction)與實現(xiàn)化(Implementation)脫耦淌铐,使得二者可以獨立地變化”肺然。橋梁模式在Java應(yīng)用中的一個非常典型的例子就是JDBC驅(qū)動器蔫缸。JDBC為所有的關(guān)系型數(shù)據(jù)庫提供一個通用的界面。一個應(yīng)用系統(tǒng)動態(tài)地選擇一個合適的驅(qū)動器际起,然后通過驅(qū)動器向數(shù)據(jù)庫引擎發(fā)出指令拾碌。這個過程就是將抽象角色的行為委派給實現(xiàn)角色的過程。
寫了一個Android的項目體現(xiàn)23中設(shè)計模式街望,項目如圖:
測試代碼:
[java]view plaincopy
publicvoidonClickSingleMode(View?view)?{//?單例
SingleMode.getInstance();
}
publicvoidonClickFactoryMethodModel(View?view)?{//?工廠方法
IProduct?iProduct?=newFactoryMethodModel();
iProduct.productMethod();
iProduct?=newTree();
iProduct.productMethod();
}
publicvoidonClickAbstractFactoryModel(View?view)?{//?抽象工廠
AbstractFactoryModel.test();
}
publicvoidonClickTemplateMethodModel(View?view)?{//?模版方法模式
TemplateMethodModel.test();
}
publicvoidonClickBuilderMode(View?view)?{//?建造者模式
BuilderMode.test();
}
publicvoidonClickProxyMode(View?view)?{//?代理模式
ProxyMode.test();
}
publicvoidonClickCloneMode(View?view)?{//?原型模式
CloneMode.test();
}
publicvoidonClickIntermediaryModel(View?view)?{//?中介者模式
IntermediaryModel.test1();
IntermediaryModel.test2();
}
publicvoidonClickCommandMode(View?view)?{//?命令模式
CommandMode.test();
}
publicvoidonChainOfResponsibilityModel(View?view)?{//?責(zé)任鏈模式
ChainOfResponsibilityModel.test();
}
publicvoidonClickDecorativeMode(View?view)?{//?裝飾模式
DecorativeMode.test();
}
publicvoidonClickStrategyMode(View?view)?{//?策略模式
StrategyMode.test();
}
publicvoidonClickIteratorModel(View?view)?{//?模式
IteratorModel.test();
}
publicvoidonClickCombinationMode(View?view)?{//?組合模式
CombinationMode.test();
}
publicvoidonClickObserverMode(View?view)?{//?觀察者模式
ObserverMode.test();
}
publicvoidonClickWindowMode(View?view)?{//?門面模式
WindowMode.test();
}
publicvoidonClickMemoMode(View?view)?{//?備忘錄模式
MemoMode.test();
}
publicvoidonClickVisitorMode(View?view)?{//?訪問者模式
VisitorMode.test();
}
publicvoidonClickStateModel(View?view)?{//?狀態(tài)模式
StateModel.test();
}
publicvoidonClickParserMode(View?view)?{//?解釋器模式
ParserMode.test();
}
publicvoidonClickFlyweightMode(View?view)?{//?享元模式
FlyweightMode.test();
}
publicvoidonClickBridgeMode(View?view)?{//?橋梁模式
BridgeMode.test();
}
如果設(shè)計模式在編碼設(shè)計生涯中用得極少校翔,主要原因是對設(shè)計模式的理解還不夠,認識不到問題的存在灾前。
因為不能正確的分析問題防症、認識問題,當然也不可能很好的解決問題了哎甲。