軟體設計原則和設計模式
這個作業屬於哪個課程 | <2022軟體程式碼開發技術> |
---|---|
這個作業要求在哪裡 | <讀書筆記----軟體設計原則、設計模式> |
這個作業的目標 | 瞭解軟體設計原則和設計模式 |
相關書籍
《軟體祕笈:設計模式那點事》——鄭阿奇
《軟體設計模式》——朱洪軍
一、設計原則
在軟體開發中,為了提高軟體系統的可維護性和可複用性,增加軟體的可擴充套件性和靈活性,程式設計師要儘量根據6條原則來開發程式,從而提高軟體開發效率、節約軟體開發成本和維護成本。
設計原則 | 說明 |
---|---|
開閉原則 | 對擴充套件開放,對修改關閉 |
里氏代換原則 | 任何基類可以出現的地方,子類一定可以出現 |
依賴倒轉原則 | 高層模組不應該依賴低層模組,兩者都應該依賴其抽象;抽象不應該依賴細節,細節應該依賴抽象 |
介面隔離原則 | 客戶端不應該被迫依賴於它不使用的方法;一個類對另一個類的依賴應該建立在最小的介面上 |
迪米特法則 | 如果兩個軟體實體無須直接通訊,那麼就不應當發生直接的相互呼叫,可以通過第三方轉發該呼叫 |
合成複用原則 | 儘量先使用組合或者聚合等關聯關係來實現,其次才考慮使用繼承關係來實現 |
二、設計模式
是一套被反覆使用、多數人知曉的、經過分類編目的、程式碼設計經驗的總結。它描述了在軟體設計過程中的一些不斷重複發生的問題,以及該問題的解決方案。設計模式共有23種。
建立型模式
用於描述怎樣建立物件,它的主要特點是將物件的建立與使用分離。
1. 單例模式
單例模式是Java中最簡單的設計模式之一。
這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不需要例項化該類的物件。
單例設計模式分類兩種:
餓漢式:類載入就會導致該單例項物件被建立
懶漢式:類載入不會導致該單例項物件被建立,而是首次使用該物件時才會建立
2. 原型模式
概念:用一個已經建立的例項作為原型,通過複製該原型物件來建立一個和原型物件相同的新物件。
原型模式的克隆分為淺克隆和深克隆。
淺克隆:建立一個新物件,新物件的屬性和原來物件完全相同,對於非基本型別屬性,仍指向原有屬性所指向的物件的記憶體地址。
深克隆:建立一個新物件,屬性中引用的其他物件也會被克隆,不再指向原有物件地址。
3. 工廠方法模式
在java中,萬物皆物件,這些物件都需要建立,如果建立的時候直接new該物件,就會對該物件耦合嚴重,假如我們要更換物件,所有new物件的地方都需要修改一遍,這顯然違背了軟體設計的開閉原則。
如果我們使用工廠來生產物件,我們就只和工廠打交道就可以了,徹底和物件解耦,如果要更換物件,直接在工廠裡更換該物件即可,達到了與物件解耦的目的;
所以說,工廠模式最大的優點就是:解耦。
概念:定義一個用於建立物件的介面,讓子類決定例項化哪個產品類物件。工廠方法使一個產品類的例項化延遲到其工廠的子類。
工廠方法模式的主要角色:
- 抽象工廠(Abstract Factory):提供了建立產品的介面,呼叫者通過它訪問具體工廠的工廠方法來建立產品。
- 具體工廠(ConcreteFactory):主要是實現抽象工廠中的抽象方法,完成具體產品的建立。
- 抽象產品(Product):定義了產品的規範,描述了產品的主要特性和功能。
- 具體產品(ConcreteProduct):實現了抽象產品角色所定義的介面,由具體工廠來建立,它同具體工廠之間一一對應。
優點:
- 使用者只需要知道具體工廠的名稱就可得到所要的產品,無須知道產品的具體建立過程;
- 在系統增加新的產品時只需要新增具體產品類和對應的具體工廠類,無須對原工廠進行任何修改,滿足開閉原則;
缺點:
- 每增加一個產品就要增加一個具體產品類和一個對應的具體工廠類,這增加了系統的複雜度。
4. 抽象工廠模式
工廠方法模式中考慮的是一類產品的生產,如畜牧場只養動物、電視機廠只生產電視機、傳智播客只培養計算機軟體專業的學生等。
這些工廠只生產同種類產品,同種類產品稱為同等級產品,也就是說:工廠方法模式只考慮生產同等級的產品,但是在現實生活中許多工廠是綜合型的工廠,能生產多等級(種類) 的產品,如電器廠既生產電視機又生產洗衣機或空調,大學既有軟體專業又有生物專業等。
抽象工廠模式將考慮多等級產品的生產,將同一個具體工廠所生產的位於不同等級的一組產品稱為一個產品族。
概念:是一種為訪問類提供一個建立一組相關或相互依賴物件的介面,且訪問類無須指定所要產品的具體類就能得到同族的不同等級的產品的模式結構。
抽象工廠模式的主要角色如下:
- 抽象工廠(Abstract Factory):提供了建立產品的介面,它包含多個建立產品的方法,可以建立多個不同等級的產品。
- 具體工廠(Concrete Factory):主要是實現抽象工廠中的多個抽象方法,完成具體產品的建立。
- 抽象產品(Product):定義了產品的規範,描述了產品的主要特性和功能,抽象工廠模式有多個抽象產品。
- 具體產品(ConcreteProduct):實現了抽象產品角色所定義的介面,由具體工廠來建立,它 同具體工廠之間是多對一的關係。
現咖啡店業務發生改變,不僅要生產咖啡還要生產甜點,如提拉米蘇、抹茶慕斯等,要是按照工廠方法模式,需要定義提拉米蘇類、抹茶慕斯類、提拉米蘇工廠、抹茶慕斯工廠、甜點工廠類,很容易發生類爆炸情況。
其中拿鐵咖啡、美式咖啡是一個產品等級,都是咖啡;提拉米蘇、抹茶慕斯也是一個產品等級;拿鐵咖啡和提拉米蘇是同一產品族(也就是都屬於義大利風味),美式咖啡和抹茶慕斯是同一產品族(也就是都屬於美式風味)。
所以這個案例可以使用抽象工廠模式實現。類圖如下:
優點:
當一個產品族中的多個物件被設計成一起工作時,它能保證客戶端始終只使用同一個產品族中的物件。
缺點:
當產品族中需要增加一個新的產品時,所有的工廠類都需要進行修改。
5. 建造者模式
概念:將一個複雜物件的構建與表示分離,使得同樣的構建過程可以建立不同的表示。
- 分離了部件的構造(由Builder來負責)和裝配(由Director負責)。 從而可以構造出複雜的物件。這個模式適用於:某個物件的構建過程複雜的情況。
- 由於實現了構建和裝配的解耦。不同的構建器,相同的裝配,也可以做出不同的物件;相同的構建器,不同的裝配順序也可以做出不同的物件。也就是實現了構建演算法、裝配演算法的解耦,實現了更好的複用。
- 建造者模式可以將部件和其組裝過程分開,一步一步建立一個複雜的物件。使用者只需要指定複雜物件的型別就可以得到該物件,而無須知道其內部的具體構造細節。
建造者(Builder)模式建立的是複雜物件,其產品的各個部分經常面臨著劇烈的變化,但將它們組合在一起的演算法卻相對穩定,所以它通常在以下場合使用。
- 建立的物件較複雜,由多個部件構成,各部件面臨著複雜的變化,但構件間的建造順序是穩定的。
- 建立複雜物件的演算法獨立於該物件的組成部分以及它們的裝配方式,即產品的構建過程和最終的表示是獨立的。
結構型模式
結構型模式描述如何將類或物件按某種佈局組成更大的結構。它分為類結構型模式和物件結構型模式,前者採用繼承機制來組織介面和類,後者釆用組合或聚合來組合物件。
由於組合關係或聚合關係比繼承關係耦合度低,滿足“合成複用原則”,所以物件結構型模式比類結構型模式具有更大的靈活性。
1. 代理模式
由於某些原因需要給某物件提供一個代理以控制對該物件的訪問。這時,訪問物件不適合或者不能直接引用目標物件,代理物件作為訪問物件和目標物件之間的中介。
2. 介面卡模式
將一個類的介面轉換成客戶希望的另外一個介面,使得原本由於介面不相容而不能一起工作的那些類能一起工作。
介面卡模式分為類介面卡模式和物件介面卡模式,前者類之間的耦合度比後者高,且要求程式設計師瞭解現有元件庫中的相關元件的內部結構,所以應用相對較少些。
3. 裝飾者模式
指在不改變現有物件結構的情況下,動態地給該物件增加一些職責(即增加其額外功能)的模式。
4. 橋接模式
將抽象與實現分離,使它們可以獨立變化。它是用組合關係代替繼承關係來實現,從而降低了抽象和實現這兩個可變維度的耦合度。
5. 外觀模式
又名門面模式,是一種通過為多個複雜的子系統提供一個一致的介面,而使這些子系統更加容易被訪問的模式。
該模式對外有一個統一介面,外部應用程式不用關心內部子系統的具體的細節,這樣會大大降低應用程式的複雜度,提高了程式的可維護性。是“迪米特法則”的典型應用。
6. 組合模式
又名部分整體模式,是用於把一組相似的物件當作一個單一的物件。組合模式依據樹形結構來組合物件,用來表示部分以及整體層次。
這種型別的設計模式屬於結構型模式,它建立了物件組的樹形結構。
7. 享元模式
運用共享技術來有效地支援大量細粒度物件的複用。它通過共享已經存在的物件來大幅度減少需要建立的物件數量、避免大量相似物件的開銷,從而提高系統資源的利用率。
行為型模式
行為型模式用於描述程式在執行時複雜的流程控制,即描述多個類或物件之間怎樣相互協作共同完成單個物件都無法單獨完成的任務,它涉及演算法與物件間職責的分配。
行為型模式分為類行為模式和物件行為模式,前者採用繼承機制來在類間分派行為,後者採用組合或聚合在物件間分配行為。
由於組合關係或聚合關係比繼承關係耦合度低,滿足“合成複用原則”,所以物件行為模式比類行為模式具有更大的靈活性。
1. 模板方法模式
定義一個操作中的演算法骨架,而將演算法的一些步驟延遲到子類中,使得子類可以不改變該演算法結構的情況下重定義該演算法的某些特定步驟。
2. 策略模式
該模式定義了一系列演算法,並將每個演算法封裝起來,使它們可以相互替換,且演算法的變化不會影響使用演算法的客戶。
策略模式屬於物件行為模式,它通過對演算法進行封裝,把使用演算法的責任和演算法的實現分割開來,並委派給不同的物件對這些演算法進行管理。
3. 命令模式
將一個請求封裝為一個物件,使發出請求的責任和執行請求的責任分割開。這樣兩者之間通過命令物件進行溝通,這樣方便將命令物件進行儲存、傳遞、呼叫、增加與管理。
4. 職責鏈模式
又名職責鏈模式,為了避免請求傳送者與多個請求處理者耦合在一起,將所有請求的處理者通過前一物件記住其下一個物件的引用而連成一條鏈;
當有請求發生時,可將請求沿著這條鏈傳遞,直到有物件處理它為止。
5. 狀態模式
對有狀態的物件,把複雜的“判斷邏輯”提取到不同的狀態物件中,允許狀態物件在其內部狀態發生改變時改變其行為。
6. 觀察者模式
又被稱為釋出-訂閱(Publish/Subscribe)模式,它定義了一種一對多的依賴關係,讓多個觀察者物件同時監聽某一個主題物件。
這個主題物件在狀態變化時,會通知所有的觀察者物件,使他們能夠自動更新自己。
7. 中介者模式
又叫調停模式,定義一箇中介角色來封裝一系列物件之間的互動,使原有物件之間的耦合鬆散,且可以獨立地改變它們之間的互動。
8. 迭代器模式
提供一個物件來順序訪問聚合物件中的一系列資料,而不暴露聚合物件的內部表示。
9. 訪問者模式
封裝一些作用於某種資料結構中的各元素的操作,它可以在不改變這個資料結構的前提下定義作用於這些元素的新的操作。
10. 備忘錄模式
又叫快照模式,在不破壞封裝性的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態,以便以後當需要時能將該物件恢復到原先儲存的狀態。
11. 直譯器模式
給定一個語言,定義它的文法表示,並定義一個直譯器,這個直譯器使用該標識來解釋語言中的句子。
在直譯器模式中,我們需要將待解決的問題,提取出規則,抽象為一種“語言”。比如加減法運算,規則為:由數值和+-符號組成的合法序列,“1+3-2” 就是這種語言的句子。
三、心得體會
在日常的開發中,使用開閉原則,在程式需要進行拓展的時候,不去修改原有的程式碼,實現熱插拔的效果,我們需要使用介面和抽象類。因為抽象靈活性好,適應性廣,只要抽象的合理,可以基本保持軟體架構的穩定。而軟體中易變的細節可以從抽象派生來的實現類來進行擴充套件,當軟體需要發生變化時,只需要根據需求重新派生一個實現類來擴充套件就可以了。而且工廠方法模式完全遵循開閉原則。比如在進行線上考試系統的開發時,使用工廠方法模式和單例模式的餓漢式返回各個例項物件。
public class DaoFactory {
private static DaoFactory factory = new DaoFactory();
private Map<String, Object> map = new ConcurrentHashMap<>();
private DaoFactory(){}
public static DaoFactory getInstance() {
return factory;
}
// 返回有關學生操作的物件
public StudentDao getStudentDao() {
StudentDao dao = (StudentDao) map.get("StudentDao");
if (dao != null) {
return dao;
} else {
dao = new StudentDao();
map.put("StudentDao", dao);
}
return dao;
}
心得:
設計模式是由前人的實踐經驗總結出來的,具有固定的實現方式,但設計原則是靈活的,需要我們認真體會和領悟。
設計模式的本質是面向物件設計原則的實際運用,是對類的封裝性、繼承性和多型性以及類的關聯關係和組合關係的充分理解。
學習設計模式可以提高我們的思維能力、程式設計能力和設計能力。