為何需要模式?
模式 是做事的方法,是實現(xiàn)目標、研磨技術(shù)的方法。
它是 思想的體現(xiàn),非具體的實現(xiàn)。
為何需要設(shè)計模式?
設(shè)計模式是一種模式,在面向?qū)ο蟮恼Z言中,它運用類與它們的方法來達到目標。
設(shè)計模式提升了代碼的水準,使之簡潔而實用,通常會使用更少的類完成目標。
設(shè)計模式的組織
任何模式的核心要素還在于它的意圖,這才是運用模式的潛在價值。
設(shè)計模式的意圖在于用更為簡便的方式來表達需求,而這些通常是Java提供的常規(guī)機制所無法滿足的。
- 接口型模式
- 職責型模式
- 構(gòu)造型模式
- 操作型模式
- 擴展型模式
接口型模式
類的接口,是類允許其他類對象訪問的方法與字段集。
接口通常代表一種承諾,即方法需要實現(xiàn)接口方法名表示的操作,遵循代碼注釋、測試和其他文檔說明。
Java將接口概念提升為獨立的結(jié)構(gòu),體現(xiàn)了接口(對象必須遵循的承諾)與實現(xiàn)(對象如何履行承諾)的分離。
抽象類與接口的區(qū)別
- 前者會有具體方法;
- 前者允許存在字段;
- 前者有構(gòu)造器;
- 可見性的級別;
- extend & implement...
接口與職責
Java接口的優(yōu)勢在于它限制了對象之間的協(xié)作,這種約束其實提供了更大的自由,即使實現(xiàn)接口的類的實現(xiàn)發(fā)生了巨大變化,接口的客戶端仍然可以不受影響。
Stub:即提供空實現(xiàn)的接口實現(xiàn)類,然后在子類中重寫對應(yīng)用程序具有重要意義的接口方法。
超越普通接口
| 如果你期望 | 可運用模式 |
|---|---|
| 適配類的接口以匹配客戶端期待的接口 | 適配器模式 |
| 為一組類提供一個簡單接口 | 外觀模式 |
| 為單個對象與復合對象提供統(tǒng)一的接口 | 合成模式 |
| 解除抽象與實現(xiàn)之間的耦合,使得兩者能夠獨立演化 | 橋接模式 |
職責型模式
面向指責的模式提供了用于集中、加強以及限制普通對象責任的技術(shù)。
常規(guī)的職責型模式
屬性與職責應(yīng)該統(tǒng)一在一起。
在面向?qū)ο蟮南到y(tǒng)中,職責的合理分配所建立的原則,是意義非凡的:
每個類和方法都應(yīng)該清晰地定義了它的職責,并且被正確地得到使用。
根據(jù)可見性控制職責
限制類、字段和方法的可見性,從而去限制其它開發(fā)人員對你所開發(fā)代碼的調(diào)用。
一個對象是能引用該類其它實例的私有成員的,因為修飾符的限定是在類級別。
超越普通職責
面向?qū)ο箝_發(fā)通常都會將職責分散到各個獨立的對象中;面向?qū)ο箝_發(fā)促進了封裝,封裝是指對象基于自己的數(shù)據(jù)進行操作。
職責分離是一種常規(guī)的做法。
| 如果你的意圖是 | 適用的模式 |
|---|---|
| 將責任集中到某個類的實例中 | 單例模式 |
| 將對象從依賴于它的對象中解耦 | 觀察者模式 |
| 將職責集中在某個類,該類可以監(jiān)督其它對象的交互 | 調(diào)停者模式 |
| 讓一個對象扮演其它對象的行為 | 代理模式 |
| 允許將請求傳遞給職責鏈的其它對象,直到這個請求被某個對象處理 | 職責鏈模式 |
| 將共享的、細粒度的對象職責集中管理 | 享元模式 |
構(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)用場景:
- 當涉及不同類中的方法擁有相同的接口時,使用“操作”;
- 當涉及如何將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ì)量。需要學會面向?qū)ο蟮囊恍┖玫脑O(shè)計原則。
Liskov替換原則要求子類的實例應(yīng)該具有父類的全部功能,應(yīng)該能夠識別和評估違反該原則的代碼;迪米特法則是一組規(guī)則,可以降低類之間的依賴,使代碼變得更加整潔。