為何需要模式凉袱?
模式 是做事的方法专甩,是實現(xiàn)目標(biāo)涤躲、研磨技術(shù)的方法种樱。
它是 思想的體現(xiàn)俊卤,非具體的實現(xiàn)消恍。
為何需要設(shè)計模式?
設(shè)計模式是一種模式约啊,在面向?qū)ο蟮恼Z言中恰矩,它運用類與它們的方法來達到目標(biāo)枢里。
設(shè)計模式提升了代碼的水準蹂午,使之簡潔而實用豆胸,通常會使用更少的類完成目標(biāo)巷疼。
設(shè)計模式的組織
任何模式的核心要素還在于它的意圖,這才是運用模式的潛在價值瓷患。
設(shè)計模式的意圖在于用更為簡便的方式來表達需求擅编,而這些通常是Java提供的常規(guī)機制所無法滿足的爱态。
- 接口型模式
- 職責(zé)型模式
- 構(gòu)造型模式
- 操作型模式
- 擴展型模式
接口型模式
類的接口境钟,是類允許其他類對象訪問的方法與字段集慨削。
接口通常代表一種承諾,即方法需要實現(xiàn)接口方法名表示的操作痘煤,遵循代碼注釋衷快、測試和其他文檔說明蘸拔。
Java將接口概念提升為獨立的結(jié)構(gòu)环葵,體現(xiàn)了接口(對象必須遵循的承諾)與實現(xiàn)(對象如何履行承諾)的分離张遭。
抽象類與接口的區(qū)別
- 前者會有具體方法菊卷;
- 前者允許存在字段;
- 前者有構(gòu)造器歉甚;
- 可見性的級別纸泄;
- extend & implement...
接口與職責(zé)
Java接口的優(yōu)勢在于它限制了對象之間的協(xié)作,這種約束其實提供了更大的自由雪营,即使實現(xiàn)接口的類的實現(xiàn)發(fā)生了巨大變化卓缰,接口的客戶端仍然可以不受影響砰诵。
Stub:即提供空實現(xiàn)的接口實現(xiàn)類茁彭,然后在子類中重寫對應(yīng)用程序具有重要意義的接口方法。
超越普通接口
如果你期望 | 可運用模式 |
---|---|
適配類的接口以匹配客戶端期待的接口 | 適配器模式 |
為一組類提供一個簡單接口 | 外觀模式 |
為單個對象與復(fù)合對象提供統(tǒng)一的接口 | 合成模式 |
解除抽象與實現(xiàn)之間的耦合摄闸,使得兩者能夠獨立演化 | 橋接模式 |
職責(zé)型模式
面向指責(zé)的模式提供了用于集中年枕、加強以及限制普通對象責(zé)任的技術(shù)熏兄。
常規(guī)的職責(zé)型模式
屬性與職責(zé)應(yīng)該統(tǒng)一在一起摩桶。
在面向?qū)ο蟮南到y(tǒng)中硝清,職責(zé)的合理分配所建立的原則转晰,是意義非凡的:
每個類和方法都應(yīng)該清晰地定義了它的職責(zé)查邢,并且被正確地得到使用侠坎。
根據(jù)可見性控制職責(zé)
限制類裙盾、字段和方法的可見性,從而去限制其它開發(fā)人員對你所開發(fā)代碼的調(diào)用庐完。
一個對象是能引用該類其它實例的私有成員的门躯,因為修飾符的限定是在類級別。
超越普通職責(zé)
面向?qū)ο箝_發(fā)通常都會將職責(zé)分散到各個獨立的對象中染乌;面向?qū)ο箝_發(fā)促進了封裝荷憋,封裝是指對象基于自己的數(shù)據(jù)進行操作勒庄。
職責(zé)分離是一種常規(guī)的做法瘫里。
如果你的意圖是 | 適用的模式 |
---|---|
將責(zé)任集中到某個類的實例中 | 單例模式 |
將對象從依賴于它的對象中解耦 | 觀察者模式 |
將職責(zé)集中在某個類谨读,該類可以監(jiān)督其它對象的交互 | 調(diào)停者模式 |
讓一個對象扮演其它對象的行為 | 代理模式 |
允許將請求傳遞給職責(zé)鏈的其它對象劳殖,直到這個請求被某個對象處理 | 職責(zé)鏈模式 |
將共享的闷尿、細粒度的對象職責(zé)集中管理 | 享元模式 |
構(gòu)造型模式
超出常規(guī)的構(gòu)造函數(shù)
如果你的意圖是 | 使用的模式 |
---|---|
在請求創(chuàng)建對象前填具,逐步收集創(chuàng)建對象需要的信息 | 構(gòu)造者模式 |
決定推遲實例化類對象 | 工廠方法模式 |
創(chuàng)建一族具有某些共同特征的對象 | 抽象工廠模式 |
根據(jù)現(xiàn)有對象創(chuàng)建一個新的對象 | 原型模式 |
通過包含了對象內(nèi)部狀態(tài)的靜態(tài)版本重新構(gòu)建一個對象 | 備忘錄模式 |
操作型模式
Java方法 級別:高于單行代碼的一個基本單元
?
涉及:整體設(shè)計劳景、架構(gòu)以及測試計劃? 實現(xiàn):面向?qū)ο缶幊痰闹行沫h(huán)節(jié)
但是方法是什么盟广?它是如何工作的?
操作和方法
- 操作:一個服務(wù)的規(guī)格說明烹吵,它可以被類的實例調(diào)用。
- 方法:操作的實現(xiàn)锈津。
這意味著操作是方法的一種抽象琼梆。
操作表示類做了什么窿吩,還表示服務(wù)提供的接口纫雁。不同的類可能用不同的方法實現(xiàn)同樣的操作。
在Java語言中携冤,方法的聲明包括方法頭和方法體兩部分曾棕。
- 方法體是一系列的指令菜循,可以通過調(diào)用方法的簽名來執(zhí)行癌幕。
- 方法頭包括方法的返回類型以及方法簽名,還可能包含訪問修飾符與異常語句橙喘。
簽名
方法的簽名包括方法名厅瞎、傳入?yún)?shù)的數(shù)量以及類型初坠。
- 方法簽名:代表了客戶調(diào)用的方法碟刺;
- 操作:是可以被請求的服務(wù)規(guī)格。
兩者的區(qū)別主要在于它們的不同應(yīng)用場景:
- 當(dāng)涉及不同類中的方法擁有相同的接口時吴菠,使用“操作”霉赡;
- 當(dāng)涉及如何將Java方法調(diào)用匹配到接受對象的方法上時穴亏,使用“簽名”嗓化。
簽名依賴于方法的名字和參數(shù)刺覆,但是不依賴于方法的返回類型史煎。
異常
….
算法和多態(tài)
算法是已經(jīng)定義好的計算程序篇梭,將數(shù)據(jù)或者數(shù)據(jù)集作為輸入,將產(chǎn)生的數(shù)據(jù)或者數(shù)據(jù)集作為輸出悍手。
算法是一個過程-----一個有輸入和輸出的指令序列坦康。
算法完成了一些事情诡延,它可能是方法的一部分,也可能調(diào)用了很多方法仑撞。
在面向?qū)ο蟮脑O(shè)計中隧哮,需要多個方法參與的算法通常依賴于多態(tài)座舍,因為
多態(tài)機制允許一個操作具有多個不同的實現(xiàn)。
多態(tài)是一個既依賴于調(diào)用的操作采蚀,又依賴于調(diào)用接收者類型的一種方法調(diào)用的原則榆鼠。
通俗地講,多態(tài)是指合適的對象調(diào)用合適的方法妆够。
小節(jié)
操作和簽名一樣神妹,是服務(wù)的規(guī)格說明鸵荠;操作意味著許多方法擁有相同的接口;簽名意味著方法的查詢規(guī)則姨伤;方法的定義包括它的簽名——方法名和參數(shù)列表庸疾,以及訪問修飾符彼硫、返回類型與方法體。方法擁有簽名和操作的實現(xiàn)词渤。
超越常規(guī)的操作
Java支持多態(tài):不同類在實現(xiàn)同一個操作時采用不同的方式缺虐;這被多種設(shè)計模式所使用礁凡。
如果你的意圖是 | 使用的模式 |
---|---|
在方法中實現(xiàn)算法顷牌,推遲對算法步驟的定義使得子類能夠重新實現(xiàn) | 模版方法模式 |
將操作分散,使得每個類都能夠表示不同的狀態(tài) | 狀態(tài)模式 |
封裝操作罪裹,使得實現(xiàn)是可以互相替換的 | 策略模式 |
用對象來封裝方法調(diào)用 | 命令模式 |
將操作分散状共,使得每個實現(xiàn)能夠運用到不同類型的集合中 | 解釋器模式 |
擴展型模式
Java編程本身就是一種擴展。
擴展代碼庫的常見技術(shù):…...冯袍;使用設(shè)計模式添加新的行為
面向?qū)ο笤O(shè)計的原則
Liskov替換原則
它的主要思想是:一個類的實例應(yīng)該具有其父類的所有功能康愤。
迪米特法則
消除代碼的壞味道
超越常規(guī)的擴展
面向擴展的模式通常涉及兩種開發(fā)角色翘瓮。
例子 | 使用的模式 |
---|---|
某個煙火模擬器的設(shè)計者設(shè)計了一個接口裤翩,要求所建立的對象必須實現(xiàn)該接口踊赠,以便于參與模擬 | 適配器模式 |
允許在運行時組合可執(zhí)行對象的工具集 | 解釋器模式 |
父類提供了一個方法每庆,要求子類來實現(xiàn)其中的一些步驟 | 模版方法模式 |
一個對象允許擴展它的行為缤灵,通過對象中封裝的方法,并且在合適的時機來調(diào)用 | 命令模式 |
通過代碼生成器來插入某些行為帖鸦,以便形成模擬對象在本季執(zhí)行的假象 | 帶咯模式 |
該設(shè)計允許注冊一些回調(diào)方法作儿,并且在對象發(fā)生變化時觸發(fā) | 觀察者模式 |
該設(shè)計允許提供已經(jīng)定義好接口的抽象操作馋劈,并且能夠添加實現(xiàn)該接口的新驅(qū)動器 | 橋接模式 |
如果你的意圖是 | 使用該模式 |
---|---|
讓開發(fā)者動態(tài)組合的行為 | 裝飾器模式 |
提供一個方法來順序訪問集合中的元素 | 迭代器模式 |
允許開發(fā)者定義一個新的操作,而無須改變分層體系中的類 | 訪問者模式 |
小節(jié)
編寫代碼的主要目的是擴展新的功能娶吞,這需要重新組織代碼械姻,改善代碼的質(zhì)量。需要學(xué)會面向?qū)ο蟮囊恍┖玫脑O(shè)計原則毫缆。
Liskov替換原則要求子類的實例應(yīng)該具有父類的全部功能苦丁,應(yīng)該能夠識別和評估違反該原則的代碼物臂;迪米特法則是一組規(guī)則棵磷,可以降低類之間的依賴仪媒,使代碼變得更加整潔。