玄子Share 設(shè)計(jì)模式 GOF 全23種 + 七大設(shè)計(jì)原則
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-NWLAOFtO-1691793071647)(./assets/%E7%8E%84%E5%AD%90Share%20%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%20GOF%20%E5%85%A823%E7%A7%8D%20+%20%E4%B8%83%E5%A4%A7%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99.png)]
目錄
GoF(Gang of Four)
GoF(Gang of Four)是四位計(jì)算機(jī)科學(xué)家(Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides)在1994年出版的書籍《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》中提出的一種設(shè)計(jì)模式分類和解決方案。該書介紹了23種常用的設(shè)計(jì)模式,分為創(chuàng)建型、結(jié)構(gòu)型和行為型三大類。這本書的社會(huì)認(rèn)可度非常高,被公認(rèn)為設(shè)計(jì)模式領(lǐng)域的經(jīng)典之作。
- 影響深遠(yuǎn):GoF的設(shè)計(jì)模式成為了軟件工程領(lǐng)域的經(jīng)典之一,對(duì)于軟件設(shè)計(jì)和架構(gòu)具有廣泛的應(yīng)用。許多軟件開發(fā)人員和團(tuán)隊(duì)都在日常工作中使用這些模式來解決常見的設(shè)計(jì)問題。
- 經(jīng)典的設(shè)計(jì)原則:GoF的設(shè)計(jì)模式不僅提供了具體的解決方案,還強(qiáng)調(diào)了面向?qū)ο笤O(shè)計(jì)的一些重要原則,如封裝、繼承、多態(tài)和接口分離等。
- 共同的設(shè)計(jì)術(shù)語:GoF提出的模式在軟件開發(fā)社區(qū)中創(chuàng)建了共同的設(shè)計(jì)術(shù)語和設(shè)計(jì)思維方式,使得開發(fā)人員之間更容易進(jìn)行溝通和理解。
- 可復(fù)用性和可維護(hù)性:通過應(yīng)用這些設(shè)計(jì)模式,開發(fā)人員可以更好地設(shè)計(jì)出具有可復(fù)用性和可維護(hù)性的軟件系統(tǒng),降低了代碼的耦合性。
總的來說,GoF的設(shè)計(jì)模式在軟件開發(fā)領(lǐng)域得到了廣泛的認(rèn)可和應(yīng)用,成為了許多軟件開發(fā)人員必備的知識(shí)和工具之一。它為軟件設(shè)計(jì)和架構(gòu)提供了有力的指導(dǎo),幫助開發(fā)人員構(gòu)建高質(zhì)量、可擴(kuò)展的軟件系統(tǒng)。
創(chuàng)建型模式(Creational Patterns)
序號(hào) | 中文名稱 | 英文名稱 | 所用設(shè)計(jì)原則 |
---|---|---|---|
1 | 工廠方法模式 | Factory Method Pattern | SRP、OCP、LSP、DIP |
2 | 抽象工廠模式 | Abstract Factory Pattern | SRP、OCP、LSP、DIP |
3 | 單例模式 | Singleton Pattern | SRP、OCP、LSP、DIP |
4 | 原型模式 | Prototype Pattern | SRP、OCP、LSP、DIP |
5 | 建造者模式 | Builder Pattern | SRP、OCP、LSP、DIP |
結(jié)構(gòu)型模式(Structural Patterns)
序號(hào) | 中文名稱 | 英文名稱 | 所用設(shè)計(jì)原則 |
---|---|---|---|
6 | 適配器模式 | Adapter Pattern | SRP、OCP、LSP、ISP、DIP |
7 | 橋接模式 | Bridge Pattern | SRP、OCP、LSP、ISP、DIP |
8 | 組合模式 | Composite Pattern | SRP、OCP、LSP、ISP、DIP |
9 | 裝飾模式 | Decorator Pattern | SRP、OCP、LSP、ISP、DIP |
10 | 外觀模式 | Facade Pattern | SRP、OCP、LSP、ISP、DIP |
11 | 享元模式 | Flyweight Pattern | SRP、OCP、LSP、ISP、DIP |
12 | 代理模式 | Proxy Pattern | SRP、OCP、LSP、ISP、DIP |
行為型模式(Behavioral Patterns)
序號(hào) | 中文名稱 | 英文名稱 | 所用設(shè)計(jì)原則 |
---|---|---|---|
13 | 責(zé)任鏈模式 | Chain of Responsibility Pattern | SRP、OCP、LSP、ISP、DIP |
14 | 命令模式 | Command Pattern | SRP、OCP、LSP、ISP、DIP |
15 | 解釋器模式 | Interpreter Pattern | SRP、OCP、LSP、ISP、DIP |
16 | 迭代器模式 | Iterator Pattern | SRP、OCP、LSP、ISP、DIP |
17 | 中介者模式 | Mediator Pattern | SRP、OCP、LSP、ISP、DIP |
18 | 備忘錄模式 | Memento Pattern | SRP、OCP、LSP、ISP、DIP |
19 | 觀察者模式 | Observer Pattern | SRP、OCP、LSP、ISP、DIP |
20 | 狀態(tài)模式 | State Pattern | SRP、OCP、LSP、ISP、DIP |
21 | 策略模式 | Strategy Pattern | SRP、OCP、LSP、ISP、DIP |
22 | 模板方法模式 | Template Method Pattern | SRP、OCP、LSP、ISP、DIP |
23 | 訪問者模式 | Visitor Pattern | SRP、OCP、LSP、ISP、DIP |
面向?qū)ο笤O(shè)計(jì)原則(OOD Principle)
面向?qū)ο笤O(shè)計(jì)原則(OODP)Object-Oriented Design Principle
- 面向?qū)ο笤O(shè)計(jì)原則是一組指導(dǎo)性準(zhǔn)則,用于幫助軟件開發(fā)人員設(shè)計(jì)和構(gòu)建高質(zhì)量、靈活、可維護(hù)和可擴(kuò)展的面向?qū)ο筌浖到y(tǒng)。
- 這些原則強(qiáng)調(diào)了良好的面向?qū)ο笤O(shè)計(jì)實(shí)踐,有助于避免常見的設(shè)計(jì)問題并提高軟件系統(tǒng)的可靠性和可重用性。
1. 單一職責(zé)原則(SRP)
單一職責(zé)原則(SRP)Single Responsibility Principle
- 每個(gè)類或模塊應(yīng)該有且只有一個(gè)單一的責(zé)任。
- 換句話說,一個(gè)類應(yīng)該只負(fù)責(zé)完成一個(gè)明確定義的功能。
- 這樣做可以降低類的復(fù)雜性,提高類的可維護(hù)性和可重用性。
2. 開閉原則(OCP)
開閉原則(OCP)Open/Closed Principle
- 軟件實(shí)體(類、模塊、函數(shù)等)應(yīng)該對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。
- 這意味著當(dāng)需要添加新功能時(shí),應(yīng)該通過擴(kuò)展現(xiàn)有代碼來實(shí)現(xiàn),而不是修改現(xiàn)有代碼。
- 這樣可以保持現(xiàn)有功能的穩(wěn)定性,并降低引入新功能時(shí)引入錯(cuò)誤的風(fēng)險(xiǎn)。
3. 里氏替換原則(LSP)
里氏替換原則(LSP)Liskov Substitution Principle
- 子類應(yīng)該能夠替換其父類并出現(xiàn)在任何使用父類的地方,而不會(huì)影響程序的正確性。
- 這就要求子類必須保持父類的行為,即子類不能修改父類的行為。
4. 接口隔離原則(ISP)
接口隔離原則(ISP) Interface Segregation Principle
- 不應(yīng)該強(qiáng)迫客戶端依賴于它們不使用的接口。
- 接口應(yīng)該被細(xì)化,只包含客戶端需要的方法,這樣可以降低類之間的耦合度,提高系統(tǒng)的靈活性和可維護(hù)性。
5. 依賴倒置原則(DIP)
依賴倒置原則(DIP)Dependency Inversion Principle
- 高層模塊不應(yīng)該依賴于低層模塊,而是應(yīng)該依賴于抽象。
- 抽象不應(yīng)該依賴于具體實(shí)現(xiàn),而是具體實(shí)現(xiàn)應(yīng)該依賴于抽象。
- 這樣可以降低模塊之間的耦合度,提高代碼的可測(cè)試性和可擴(kuò)展性。
6. 迪米特法則(LOD)
迪米特法則(LoD)Law Of Demeter
- 也稱為最少知識(shí)原則。
- 一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有盡可能少的了解,只與直接的朋友進(jìn)行交互。
- 這樣可以降低類之間的耦合度,使系統(tǒng)更加靈活和易于維護(hù)。
7. 合成復(fù)用原則(CRP)
合成復(fù)用原則(CRP)Composite Reuse Principle
- 盡量使用組合/聚合的方式而不是繼承關(guān)系達(dá)到軟件復(fù)用的目的,是 has-a 關(guān)系,而不是通過繼承。
- 該原則促使開發(fā)者在設(shè)計(jì)中更多地考慮對(duì)象之間的組合關(guān)系,以達(dá)到模塊化、靈活性和可維護(hù)性的目標(biāo)。
這些面向?qū)ο笤O(shè)計(jì)原則是設(shè)計(jì)模式的基礎(chǔ),它們指導(dǎo)著我們?nèi)绾卧O(shè)計(jì)出更加健壯、靈活和可維護(hù)的面向?qū)ο筌浖到y(tǒng)。
遵循這些原則有助于提高代碼的質(zhì)量,減少重構(gòu)的需求,并幫助我們構(gòu)建出更好的軟件。
創(chuàng)建型模式 (Creational Patterns)
創(chuàng)建型模式是設(shè)計(jì)模式中的一類,主要關(guān)注如何創(chuàng)建對(duì)象以及對(duì)象的實(shí)例化過程。它們提供了一種靈活、可復(fù)用的方式來創(chuàng)建對(duì)象,同時(shí)隱藏了對(duì)象創(chuàng)建的細(xì)節(jié),從而降低了系統(tǒng)的耦合性。
這些創(chuàng)建型模式各自適用于不同的場(chǎng)景,可以根據(jù)具體需求來選擇合適的設(shè)計(jì)模式來實(shí)現(xiàn)對(duì)象的創(chuàng)建和初始化。它們的共同目標(biāo)是降低對(duì)象的創(chuàng)建和使用之間的耦合,提供更加靈活和可擴(kuò)展的代碼結(jié)構(gòu)。
工廠方法模式(Factory Method Pattern)
在學(xué)習(xí)工廠方法模式之前建議先學(xué)習(xí)文章最后一章《必要拓展》中的簡(jiǎn)單工廠模式(Simple Factory Pattern)
1. 簡(jiǎn)單介紹
工廠方法模式(Factory Method Pattern)定義一個(gè)創(chuàng)建對(duì)象的接口,但由子類決定具體實(shí)例化哪個(gè)類??蛻舳酥恍枰拦S接口,而不關(guān)心具體的產(chǎn)品類。
2. 實(shí)際問題
假設(shè)你是一家汽車制造公司,你有多個(gè)型號(hào)的汽車需要生產(chǎn),每種型號(hào)的汽車有不同的配置和特性。你需要一個(gè)靈活的方式來生產(chǎn)不同型號(hào)的汽車,并且在將來能夠輕松添加新的汽車型號(hào)。
3. 解決方案
- 定義一個(gè)產(chǎn)品接口,規(guī)范產(chǎn)品的行為。
- 創(chuàng)建一個(gè)工廠接口,包含一個(gè)工廠方法用于創(chuàng)建產(chǎn)品對(duì)象。
- 對(duì)每個(gè)具體產(chǎn)品,創(chuàng)建一個(gè)具體產(chǎn)品類,實(shí)現(xiàn)產(chǎn)品接口。
- 對(duì)每個(gè)具體產(chǎn)品,創(chuàng)建一個(gè)具體工廠類,實(shí)現(xiàn)工廠接口,負(fù)責(zé)創(chuàng)建具體產(chǎn)品的實(shí)例。
// 產(chǎn)品接口:汽車
interface Car {
void assemble();
}
// 具體產(chǎn)品:SUV 汽車
class SUVCar implements Car {
@Override
public void assemble() {
System.out.println("組裝SUV汽車");
}
}
// 具體產(chǎn)品:轎車
class SedanCar implements Car {
@Override
public void assemble() {
System.out.println("組裝轎車");
}
}
// 工廠接口:汽車工廠
interface CarFactory {
Car createCar();
}
// 具體工廠:SUV 汽車工廠
class SUVCarFactory implements CarFactory {
@Override
public Car createCar() {
return new SUVCar();
}
}
// 具體工廠:轎車工廠
class SedanCarFactory implements CarFactory {
@Override
public Car createCar() {
return new SedanCar();
}
}
// 調(diào)用代碼
public class XZ {
public static void main(String[] args) {
System.out.println("===========SUV===========");
Car suvCar = new SUVCarFactory().createCar();
suvCar.assemble();
System.out.println("===========Sedan===========");
Car sedanCar = new SedanCarFactory().createCar();
sedanCar.assemble();
}
}
4. 類關(guān)系圖
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-q3KXdmJK-1691793071648)(./assets/FactoryMethodPattern.png)]
5. 應(yīng)用場(chǎng)景
- 當(dāng)一個(gè)類無法預(yù)先知道它需要?jiǎng)?chuàng)建的對(duì)象的確切類時(shí),使用工廠方法可以延遲對(duì)象的實(shí)例化,使得具體的實(shí)例化由子類來決定。
- 當(dāng)需要在運(yùn)行時(shí)動(dòng)態(tài)地選擇創(chuàng)建某個(gè)類的對(duì)象時(shí),工廠方法提供了一種靈活的解決方案。
6. 易錯(cuò)點(diǎn)
- 忘記實(shí)現(xiàn)產(chǎn)品接口:每個(gè)具體產(chǎn)品都必須實(shí)現(xiàn)產(chǎn)品接口,否則無法通過工廠方法創(chuàng)建產(chǎn)品對(duì)象。
- 忘記實(shí)現(xiàn)工廠接口:每個(gè)具體工廠都必須實(shí)現(xiàn)工廠接口,以提供工廠方法來創(chuàng)建產(chǎn)品對(duì)象。
7. 優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 通過工廠方法,將產(chǎn)品的創(chuàng)建與使用解耦,客戶端不需要知道具體產(chǎn)品的類名,只需要通過工廠接口來創(chuàng)建對(duì)象,降低了耦合度。
- 具體產(chǎn)品的新增和變更對(duì)客戶端代碼沒有影響,只需要新增或修改相應(yīng)的具體工廠類即可。
缺點(diǎn)
- 每新增一個(gè)具體產(chǎn)品,都需要新增一個(gè)相應(yīng)的具體工廠類,導(dǎo)致類的個(gè)數(shù)增加,增加了系統(tǒng)的復(fù)雜性。
8. 總結(jié)
工廠方法模式是一種創(chuàng)建型設(shè)計(jì)模式,通過將產(chǎn)品的創(chuàng)建與使用解耦,讓子類決定實(shí)例化哪個(gè)類。這樣可以提高代碼的靈活性和可擴(kuò)展性,使得系統(tǒng)的演化和維護(hù)更加容易。雖然增加了類的個(gè)數(shù),但對(duì)于復(fù)雜系統(tǒng)的開發(fā)來說,這是值得的權(quán)衡。在需要?jiǎng)討B(tài)地選擇創(chuàng)建對(duì)象,或者有多個(gè)類似產(chǎn)品等級(jí)結(jié)構(gòu)的情況下,工廠方法模式是一個(gè)很好的選擇。
抽象工廠模式(Abstract Factory Pattern)
1. 簡(jiǎn)單介紹
抽象工廠模式(Abstract Factory Pattern)提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無需指定它們具體的類。抽象工廠可以創(chuàng)建多個(gè)不同類型的產(chǎn)品。
2. 實(shí)際問題
假設(shè)你是一家家具制造公司,你有多種類型的家具,如沙發(fā)、床、桌子等,每種類型的家具有不同的風(fēng)格和材料。你需要一種靈活的方式來生產(chǎn)不同類型和風(fēng)格的家具,并且在將來能夠輕松添加新的家具類型和風(fēng)格。
3. 解決方案
// 產(chǎn)品接口:沙發(fā)
interface Sofa {
void sitOn();
}
// 產(chǎn)品接口:床
interface Bed {
void sleepOn();
}
// 具體產(chǎn)品:現(xiàn)代風(fēng)格沙發(fā)
class ModernSofa implements Sofa {
@Override
public void sitOn() {
System.out.println("坐在現(xiàn)代風(fēng)格的沙發(fā)上");
}
}
// 具體產(chǎn)品:現(xiàn)代風(fēng)格床
class ModernBed implements Bed {
@Override
public void sleepOn() {
System.out.println("睡在現(xiàn)代風(fēng)格的床上");
}
}
// 具體產(chǎn)品:古典風(fēng)格沙發(fā)
class ClassicalSofa implements Sofa {
@Override
public void sitOn() {
System.out.println("坐在古典風(fēng)格的沙發(fā)上");
}
}
// 具體產(chǎn)品:古典風(fēng)格床
class ClassicalBed implements Bed {
@Override
public void sleepOn() {
System.out.println("睡在古典風(fēng)格的床上");
}
}
// 抽象工廠接口:家具工廠
interface FurnitureFactory {
Sofa createSofa();
Bed createBed();
}
// 具體工廠:現(xiàn)代風(fēng)格家具工廠
class ModernFurnitureFactory implements FurnitureFactory {
@Override
public Sofa createSofa() {
return new ModernSofa();
}
@Override
public Bed createBed() {
return new ModernBed();
}
}
// 具體工廠:古典風(fēng)格家具工廠
class ClassicalFurnitureFactory implements FurnitureFactory {
@Override
public Sofa createSofa() {
return new ClassicalSofa();
}
@Override
public Bed createBed() {
return new ClassicalBed();
}
}
// 調(diào)用代碼
public class XZ {
public static void main(String[] args) {
System.out.println("===========現(xiàn)代家具===========");
ModernFurnitureFactory modernFurnitureFactory = new ModernFurnitureFactory();
Bed modernBed = modernFurnitureFactory.createBed();
modernBed.sleepOn();
Sofa modernSofa = modernFurnitureFactory.createSofa();
modernSofa.sitOn();
System.out.println("======古典家具========");
ClassicalFurnitureFactory classicalFurnitureFactory = new ClassicalFurnitureFactory();
Bed classicaBed = classicalFurnitureFactory.createBed();
classicaBed.sleepOn();
Sofa classicaSofa = classicalFurnitureFactory.createSofa();
classicaSofa.sitOn();
}
}
4. 類關(guān)系圖
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-o80LAUXY-1691793071648)(./assets/AbstractFactoryPattern.png)]
5. 應(yīng)用場(chǎng)景
- 當(dāng)需要?jiǎng)?chuàng)建一組相關(guān)或相互依賴的對(duì)象時(shí),可以使用抽象工廠模式。例如,創(chuàng)建不同風(fēng)格的家具,或者創(chuàng)建不同主題的界面元素等。
- 當(dāng)希望系統(tǒng)在未來能夠支持新的產(chǎn)品種類或產(chǎn)品族,而不需要修改現(xiàn)有代碼時(shí),抽象工廠模式提供了一種擴(kuò)展的解決方案。
6. 易錯(cuò)點(diǎn)
- 在添加新的產(chǎn)品族時(shí),需要修改抽象工廠接口及其所有子類,可能導(dǎo)致較大的改動(dòng)。
- 在添加新的產(chǎn)品等級(jí)結(jié)構(gòu)時(shí),需要修改抽象工廠接口及其所有子類,可能導(dǎo)致較大的改動(dòng)。
7. 優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 將一組相關(guān)的產(chǎn)品封裝在一起,客戶端使用抽象接口來創(chuàng)建產(chǎn)品,不需要關(guān)心具體的實(shí)現(xiàn)細(xì)節(jié),降低了客戶端和具體產(chǎn)品類之間的耦合。
- 可以輕松替換不同的工廠類來創(chuàng)建不同的產(chǎn)品族,增加新的產(chǎn)品族也方便,符合開閉原則。
缺點(diǎn)
- 增加新的產(chǎn)品族或產(chǎn)品等級(jí)結(jié)構(gòu)時(shí),需要修改抽象工廠接口及其所有子類,可能導(dǎo)致較大的改動(dòng)。
- 當(dāng)產(chǎn)品族和產(chǎn)品等級(jí)結(jié)構(gòu)過于復(fù)雜時(shí),抽象工廠模式的類的數(shù)量可能會(huì)增加,導(dǎo)致系統(tǒng)復(fù)雜性增加。
8. 總結(jié)
抽象工廠模式是一種創(chuàng)建型設(shè)計(jì)模式,通過提供一個(gè)接口來創(chuàng)建一組相關(guān)或相互依賴的對(duì)象,將一系列產(chǎn)品封裝在一起,使得客戶端不需要知道具體產(chǎn)品的類名,只需使用抽象接口即可。抽象工廠模式適用于創(chuàng)建一組相關(guān)的產(chǎn)品,且希望系統(tǒng)能夠輕松支持新的產(chǎn)品族或產(chǎn)品等級(jí)結(jié)構(gòu)的場(chǎng)景。在使用抽象工廠模式時(shí),需要注意在添加新的產(chǎn)品族或產(chǎn)品等級(jí)結(jié)構(gòu)時(shí),可能需要修改較多的代碼。
單例模式(Singleton Pattern)
1. 簡(jiǎn)單介紹
單例模式(Singleton Pattern)確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問點(diǎn)。這樣可以控制對(duì)象的創(chuàng)建和訪問,通常用于管理共享資源或全局配置。
2. 實(shí)際問題
在現(xiàn)實(shí)世界中,我們可能會(huì)遇到這樣的問題:希望某個(gè)類在整個(gè)應(yīng)用程序中只能擁有一個(gè)實(shí)例,不論在何處訪問該類,始終獲取到相同的唯一實(shí)例。
3. 解決方案
- 懶漢式單例
懶漢式是指在首次使用時(shí)才創(chuàng)建實(shí)例。解決方案為在類內(nèi)部定義一個(gè)私有靜態(tài)變量作為該類的唯一實(shí)例,并提供一個(gè)公共靜態(tài)方法來獲取該實(shí)例。
// 懶漢式單例
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
// 私有構(gòu)造方法,防止其他類通過 new 創(chuàng)建實(shí)例
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
// 調(diào)用代碼
public class XZ {
public static void main(String[] args) {
// 獲取懶漢式單例實(shí)例
LazySingleton instance1 = LazySingleton.getInstance();
LazySingleton instance2 = LazySingleton.getInstance();
// 驗(yàn)證是否為同一實(shí)例
System.out.println(instance1 == instance2);
// Output: true
}
}
- 餓漢式單例
餓漢式是指在類加載時(shí)就創(chuàng)建實(shí)例。解決方案為在類定義時(shí)直接創(chuàng)建一個(gè)私有靜態(tài)實(shí)例,并提供一個(gè)公共靜態(tài)方法來獲取該實(shí)例。
// 餓漢式單例
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {}
// 私有構(gòu)造方法,防止其他類通過 new 創(chuàng)建實(shí)例
public static EagerSingleton getInstance() {
return instance;
}
}
// 調(diào)用代碼
public class XZ {
public static void main(String[] args) {
// 獲取餓漢式單例實(shí)例
EagerSingleton instance1 = EagerSingleton.getInstance();
EagerSingleton instance2 = EagerSingleton.getInstance();
// 驗(yàn)證是否為同一實(shí)例
System.out.println(instance1 == instance2);
// Output: true
}
}
- 雙重校驗(yàn)鎖單例
雙重校驗(yàn)鎖單例是一種在懶漢式基礎(chǔ)上進(jìn)行改進(jìn)的解決方案,旨在減少不必要的同步開銷。
// 雙重校驗(yàn)鎖單例
public class DoubleCheckedSingleton {
private volatile static DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {}
// 私有構(gòu)造方法,防止其他類通過 new 創(chuàng)建實(shí)例
public static DoubleCheckedSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}
// 調(diào)用代碼
public class XZ {
public static void main(String[] args) {
// 獲取雙重校驗(yàn)鎖單例實(shí)例
DoubleCheckedSingleton instance1 = DoubleCheckedSingleton.getInstance();
DoubleCheckedSingleton instance2 = DoubleCheckedSingleton.getInstance();
// 驗(yàn)證是否為同一實(shí)例
System.out.println(instance1 == instance2);
// Output: true
}
}
- 枚舉單例
枚舉單例是一種簡(jiǎn)潔且線程安全的單例模式解決方案。在Java中,枚舉類型是天然的單例,保證在任何情況下都只有一個(gè)實(shí)例。
// 枚舉單例
public enum EnumSingleton {
INSTANCE;
// 可以添加其他方法和屬性
}
// 調(diào)用代碼
public class XZ {
public static void main(String[] args) {
// 獲取枚舉單例實(shí)例
EnumSingleton instance1 = EnumSingleton.INSTANCE;
EnumSingleton instance2 = EnumSingleton.INSTANCE;
// 驗(yàn)證是否為同一實(shí)例
System.out.println(instance1 == instance2);
// Output: true
}
}
在每個(gè)示例中,我們都通過相應(yīng)的靜態(tài)方法獲取單例實(shí)例,并通過比較引用地址驗(yàn)證是否為同一實(shí)例。由于單例模式保證在整個(gè)應(yīng)用程序中只有一個(gè)實(shí)例,所以輸出結(jié)果都應(yīng)該是
true
。
4. 類關(guān)系圖
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-cIdeohu0-1691793071648)(./assets/SingletonPattern.png)]
5. 應(yīng)用場(chǎng)景
- 需要在整個(gè)應(yīng)用程序中共享某個(gè)資源,例如配置信息、數(shù)據(jù)庫連接等。
- 控制資源的并發(fā)訪問,避免資源沖突。
6. 易錯(cuò)點(diǎn)
- 線程安全問題:懶漢式和雙重校驗(yàn)鎖單例在多線程環(huán)境下可能會(huì)創(chuàng)建多個(gè)實(shí)例,需要采取同步措施保證線程安全,但同步會(huì)影響性能。
- 反序列化問題:如果單例類實(shí)現(xiàn)了Serializable接口,當(dāng)對(duì)象被反序列化時(shí),可能會(huì)創(chuàng)建新的實(shí)例,破壞單例特性,需要通過readResolve()方法解決。
7. 優(yōu)缺點(diǎn)
懶漢式單例模式
-
優(yōu)點(diǎn)
- 實(shí)現(xiàn)懶加載,只有在實(shí)例需要時(shí)才會(huì)創(chuàng)建。
- 簡(jiǎn)單易懂。
-
缺點(diǎn)
- 線程安全需要額外考慮,可能會(huì)影響性能。
- 反序列化可能會(huì)破壞單例特性。
餓漢式單例模式
-
優(yōu)點(diǎn)
- 實(shí)現(xiàn)簡(jiǎn)單,不需要考慮線程安全問題。
- 線程安全,可以直接用于多線程環(huán)境。
-
缺點(diǎn)
- 不支持懶加載,可能導(dǎo)致資源浪費(fèi)。
雙重校驗(yàn)鎖單例模式
-
優(yōu)點(diǎn)
- 實(shí)現(xiàn)懶加載,只有在實(shí)例需要時(shí)才會(huì)創(chuàng)建。
- 在多線程環(huán)境下保持了較好的性能。
-
缺點(diǎn)
- 實(shí)現(xiàn)相對(duì)復(fù)雜,容易出錯(cuò)。
- JDK 1.5之前的版本中可能存在雙重檢查鎖失效的問題。
枚舉單例模式
-
優(yōu)點(diǎn)
- 簡(jiǎn)潔且線程安全,天然保證只有一個(gè)實(shí)例。
- 支持其他方法和屬性的定義。
-
缺點(diǎn)
- 不能實(shí)現(xiàn)懶加載,實(shí)例在類加載時(shí)就被創(chuàng)建。
8. 總結(jié)
懶漢式、餓漢式、枚舉單例和雙重校驗(yàn)鎖單例是常見的單例模式解決方案。懶漢式適用于需要懶加載的場(chǎng)景,但需注意線程安全和反序列化問題。餓漢式適用于不需要懶加載的場(chǎng)景,且線程安全。枚舉單例是一種簡(jiǎn)潔且線程安全的解決方案,但不能實(shí)現(xiàn)懶加載。雙重校驗(yàn)鎖單例在懶加載的基礎(chǔ)上進(jìn)行了改進(jìn),可以在多線程環(huán)境下保持較好的性能,但實(shí)現(xiàn)相對(duì)復(fù)雜。在選擇解決方案時(shí),需根據(jù)具體場(chǎng)景的需求和性能要求做出選擇。
原型模式(Prototype Pattern)
1. 簡(jiǎn)單介紹
原型模式(Prototype Pattern)通過復(fù)制現(xiàn)有對(duì)象來創(chuàng)建新的對(duì)象,避免了使用常規(guī)構(gòu)造函數(shù)來創(chuàng)建對(duì)象,從而提高性能和靈活性。
2. 實(shí)際問題
在現(xiàn)實(shí)世界中,我們可能會(huì)遇到這樣的問題:希望創(chuàng)建一個(gè)對(duì)象的副本,并且可以根據(jù)原對(duì)象進(jìn)行快速的復(fù)制和修改。
3. 解決方案
原型模式是一種創(chuàng)建型設(shè)計(jì)模式,它通過復(fù)制現(xiàn)有對(duì)象來創(chuàng)建新對(duì)象。Java中可以通過實(shí)現(xiàn)Cloneable接口和重寫clone()方法來實(shí)現(xiàn)原型模式。
- 淺克隆
// 原型對(duì)象類
public class Prototype implements Cloneable {
private String data;
public Prototype(String data) {
this.data = data;
}
// 重寫clone方法,實(shí)現(xiàn)淺拷貝
@Override
public Prototype clone() throws CloneNotSupportedException {
return (Prototype) super.clone();
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
// 調(diào)用代碼
public class XZ {
public static void main(String[] args) throws CloneNotSupportedException {
// 創(chuàng)建原型對(duì)象
Prototype originalPrototype = new Prototype("玄子Share");
// 克隆原型對(duì)象
Prototype clonedPrototype = originalPrototype.clone();
System.out.println("新對(duì)象克隆的數(shù)據(jù): " + clonedPrototype.getData());
// 修改克隆對(duì)象的數(shù)據(jù)
clonedPrototype.setData("XuanZiShare");
System.out.println("獲取修改后的數(shù)據(jù): " + clonedPrototype.getData());
System.out.println("獲取源對(duì)象的數(shù)據(jù): " + originalPrototype.getData());
// 修改新對(duì)象數(shù)據(jù)不影響源對(duì)象
}
}
- 深克隆
4. 類關(guān)系圖
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-EAThpScU-1691793071649)(./assets/PrototypePattern.png)]
5. 應(yīng)用場(chǎng)景
- 需要?jiǎng)?chuàng)建復(fù)雜對(duì)象,但創(chuàng)建過程較為耗時(shí)。
- 需要?jiǎng)?chuàng)建大量相似對(duì)象,復(fù)制現(xiàn)有對(duì)象比重新創(chuàng)建更高效。
6. 易錯(cuò)點(diǎn)
淺拷貝問題:默認(rèn)情況下,clone()方法執(zhí)行的是淺拷貝,即只復(fù)制基本類型的字段和引用類型的地址,而不復(fù)制引用類型對(duì)象本身。如果對(duì)象中包含引用類型字段,需要注意處理深拷貝問題。
7. 優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 提高對(duì)象的創(chuàng)建效率,避免重復(fù)執(zhí)行初始化操作。
- 方便快速創(chuàng)建和修改對(duì)象副本。
缺點(diǎn)
- 如果對(duì)象的復(fù)制過程較為復(fù)雜,可能需要實(shí)現(xiàn)深拷貝。
- 在處理引用類型字段時(shí)需要特別注意,避免共享引用對(duì)象導(dǎo)致意外修改。
8. 總結(jié)
原型模式是一種創(chuàng)建型設(shè)計(jì)模式,通過復(fù)制現(xiàn)有對(duì)象來創(chuàng)建新對(duì)象。在Java中,可以通過實(shí)現(xiàn)Cloneable接口和重寫clone()方法來實(shí)現(xiàn)原型模式。原型模式適用于需要?jiǎng)?chuàng)建復(fù)雜對(duì)象或大量相似對(duì)象的場(chǎng)景,可以提高對(duì)象的創(chuàng)建效率,并方便快速創(chuàng)建和修改對(duì)象副本。需要注意處理引用類型字段時(shí)的淺拷貝問題,并根據(jù)具體情況考慮是否需要實(shí)現(xiàn)深拷貝。
建造者模式(Builder Pattern)
1. 簡(jiǎn)單介紹
建造者模式(Builder Pattern)將一個(gè)復(fù)雜對(duì)象的構(gòu)建過程與其表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
2. 實(shí)際問題
在現(xiàn)實(shí)世界中,我們可能會(huì)遇到這樣的問題:希望構(gòu)建一個(gè)復(fù)雜的對(duì)象,該對(duì)象有多個(gè)可選屬性,并且在創(chuàng)建過程中可以靈活組合這些屬性。
3. 解決方案
建造者模式是一種創(chuàng)建型設(shè)計(jì)模式,它通過將對(duì)象的構(gòu)建過程和表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。建造者模式通常包含一個(gè)Builder接口和一個(gè)ConcreteBuilder實(shí)現(xiàn)類,以及一個(gè)Director類來指導(dǎo)構(gòu)建過程。
- 建造者模式
// 建造者接口
public interface Builder {
void buildPart1();
void buildPart2();
void buildPart3();
Product getResult();
}
// 具體建造者
public class ConcreteBuilder implements Builder {
private final Product product = new Product();
public void buildPart1() {
product.setPart1("Part1");
}
public void buildPart2() {
product.setPart2("Part2");
}
public void buildPart3() {
product.setPart3("Part3");
}
public Product getResult() {
return product;
}
}
// 產(chǎn)品類
public class Product {
private String part1;
private String part2;
private String part3;
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
public String getPart3() {
return part3;
}
public void setPart3(String part3) {
this.part3 = part3;
}
@Override
public String toString() {
return "Product{" +
"part1='" + part1 + '\'' +
", part2='" + part2 + '\'' +
", part3='" + part3 + '\'' +
'}';
}
}
// 指導(dǎo)者類
public class Director {
public void construct(Builder builder) {
builder.buildPart1();
builder.buildPart2();
builder.buildPart3();
}
}
// 調(diào)用代碼
public class XZ {
public static void main(String[] args) {
// 創(chuàng)建指導(dǎo)者和建造者對(duì)象
Director director = new Director();
Builder builder = new ConcreteBuilder();
// 指導(dǎo)建造過程并獲取產(chǎn)品對(duì)象
director.construct(builder);
Product product = builder.getResult();
// 輸出產(chǎn)品信息
System.out.println(product);
// Output: Product{part1='Part1', part2='Part2', part3='Part3'}
}
}
產(chǎn)品信息順序固定
- 建造者模式(無指揮
Director
)
// 建造者接口
public interface Builder {
Builder buildPart1(String part);
Builder buildPart2(String part);
Builder buildPart3(String part);
Product getResult();
}
// 具體建造者
public class ConcreteBuilder implements Builder {
private final Product product = new Product();
public Builder buildPart1(String part) {
product.setPart1(part);
return this;
}
public Builder buildPart2(String part) {
product.setPart2(part);
return this;
}
public Builder buildPart3(String part) {
product.setPart3(part);
return this;
}
public Product getResult() {
return product;
}
}
// 產(chǎn)品類
public class Product {
private String part1 = "part1";
private String part2 = "part1";
private String part3 = "part1";
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
public String getPart3() {
return part3;
}
public void setPart3(String part3) {
this.part3 = part3;
}
@Override
public String toString() {
return "Product{" +
"part1='" + part1 + '\'' +
", part2='" + part2 + '\'' +
", part3='" + part3 + '\'' +
'}';
}
}
// 調(diào)用代碼
public class XZ {
public static void main(String[] args) {
// 創(chuàng)建指導(dǎo)者和建造者對(duì)象
ConcreteBuilder concreteBuilder = new ConcreteBuilder();
Product product = concreteBuilder.getResult();
// 輸出產(chǎn)品信息
System.out.println(product);
// Output: Product{part1='Part1', part2='Part2', part3='Part3'}
System.out.println("============================");
// 創(chuàng)建指導(dǎo)者和建造者對(duì)象
ConcreteBuilder concreteBuilder2 = new ConcreteBuilder();
// 鏈?zhǔn)骄幊蹋涸谠瓉淼幕A(chǔ)上,可自由組合,若不組合,則默認(rèn)
Product product2 = concreteBuilder2.buildPart1("part2").buildPart2("part1").buildPart3("part3").getResult();
// 輸出產(chǎn)品信息
System.out.print(product2);
// Output: Product{part1='part2', part2='part1', part3='part3'}
}
}
產(chǎn)品信息順序可自由搭配
4. 類關(guān)系圖
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-zpNk258S-1691793071649)(./assets/BuilderPatternDirector.png)]
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-4EN9GsQi-1691793071649)(./assets/BuilderPatternChain.png)]
5. 應(yīng)用場(chǎng)景
- 需要?jiǎng)?chuàng)建復(fù)雜對(duì)象,且對(duì)象的構(gòu)建過程相對(duì)穩(wěn)定,但表示可以靈活組合的場(chǎng)景。
- 當(dāng)一個(gè)對(duì)象有多個(gè)可選屬性,且屬性之間有依賴關(guān)系時(shí),可以使用建造者模式進(jìn)行構(gòu)建。
6. 易錯(cuò)點(diǎn)
- 需要根據(jù)實(shí)際需求定義建造者接口和具體建造者類,確保建造過程的正確性和靈活性。
- 在指導(dǎo)者類中指導(dǎo)建造過程,確保正確的建造順序和步驟。
7. 優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 將對(duì)象的構(gòu)建過程和表示分離,使得構(gòu)建過程可以創(chuàng)建不同的表示,提高了構(gòu)建過程的靈活性。
- 可以隱藏產(chǎn)品的內(nèi)部結(jié)構(gòu),使得客戶端只關(guān)注產(chǎn)品的高層接口。
缺點(diǎn)
- 需要定義多個(gè)類,增加了代碼復(fù)雜性。
- 不適用于只有少量可選屬性的對(duì)象,過度使用建造者模式可能會(huì)導(dǎo)致代碼冗余。
8. 總結(jié)
建造者模式是一種創(chuàng)建型設(shè)計(jì)模式,它通過將對(duì)象的構(gòu)建過程和表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。在Java中,可以通過定義建造者接口和具體建造者類來實(shí)現(xiàn)建造者模式,并通過指導(dǎo)者類指導(dǎo)建造過程。建造者模式適用于需要?jiǎng)?chuàng)建復(fù)雜對(duì)象,且對(duì)象的構(gòu)建過程相對(duì)穩(wěn)定但表示可以靈活組合的場(chǎng)景。需要注意定義建造者接口和具體建造者類,確保建造過程的正確性和靈活性。同時(shí),建造者模式也應(yīng)避免過度使用,以免造成代碼冗余。
結(jié)構(gòu)型模式 (Structural Patterns)
結(jié)構(gòu)型模式(Structural Patterns)是設(shè)計(jì)模式中的一類,它主要關(guān)注對(duì)象和類的組合,以實(shí)現(xiàn)更大的結(jié)構(gòu),以及改變或簡(jiǎn)化類之間的交互方式。這些模式使得不同類和對(duì)象之間的關(guān)系更加靈活,同時(shí)也降低了系統(tǒng)的耦合度,使系統(tǒng)更易于維護(hù)和擴(kuò)展。
結(jié)構(gòu)型模式在軟件開發(fā)中起到了重要的作用,它們幫助我們?cè)谠O(shè)計(jì)階段選擇合適的模式,提高系統(tǒng)的設(shè)計(jì)質(zhì)量和性能,并促進(jìn)代碼的重用和維護(hù)。不同的結(jié)構(gòu)型模式適用于不同的場(chǎng)景和需求,通過合理使用結(jié)構(gòu)型模式,可以讓系統(tǒng)更加靈活、可擴(kuò)展和易于理解。
適配器模式(Adapter Pattern)
橋接模式(Bridge Pattern)
組合模式(Composite Pattern)
裝飾模式(Decorator Pattern)
外觀模式(Facade Pattern)
享元模式(Flyweight Pattern)
代理模式(Proxy Pattern)
行為型模式 (Behavioral Patterns)
行為型模式(Behavioral Patterns)是設(shè)計(jì)模式的一種分類,它關(guān)注對(duì)象之間的交互和責(zé)任分配。行為型模式主要用于描述對(duì)象之間的通信方式和協(xié)作方式,以及對(duì)象如何相互影響和完成各自的任務(wù)。在行為型模式中,關(guān)注的是對(duì)象的行為和算法的分配,而不是對(duì)象的結(jié)構(gòu)。
每種行為型模式都解決了特定類型的問題,可以根據(jù)實(shí)際的需求選擇合適的模式來設(shè)計(jì)和實(shí)現(xiàn)軟件系統(tǒng)。這些模式在軟件開發(fā)中具有廣泛的應(yīng)用,能夠提高代碼的可維護(hù)性和擴(kuò)展性,降低代碼的耦合度,使得系統(tǒng)更加靈活和易于維護(hù)。
責(zé)任鏈模式(Chain of Responsibility Pattern)
命令模式 Command Pattern
解釋器模式(Interpreter Pattern)
迭代器模式 Iterator Pattern
中介者模式 Mediator Pattern
備忘錄模式 Memento Pattern
觀察者模式 Observer Pattern
狀態(tài)模式 State Pattern
策略模式 Strategy Pattern
模板方法模式 Template Method Pattern
訪問者模式 Visitor Pattern
必要性拓展
簡(jiǎn)單工廠模式(Simple Factory Pattern)
1. 簡(jiǎn)單介紹
簡(jiǎn)單工廠模式(Simple Factory Pattern)雖然它不在 GoF 的列表中,但在實(shí)際開發(fā)中,簡(jiǎn)單工廠模式是一種經(jīng)常被使用的設(shè)計(jì)模式。它簡(jiǎn)化了對(duì)象的創(chuàng)建過程,提高了代碼的可維護(hù)性和擴(kuò)展性。
2. 實(shí)際問題
假設(shè)你正在開發(fā)一個(gè)計(jì)算器應(yīng)用程序,用戶可以輸入兩個(gè)操作數(shù)和運(yùn)算符,然后應(yīng)用程序會(huì)根據(jù)輸入的運(yùn)算符進(jìn)行相應(yīng)的計(jì)算,并返回結(jié)果。不同的運(yùn)算符對(duì)應(yīng)不同的計(jì)算方法,例如加法、減法、乘法和除法等。你希望設(shè)計(jì)一個(gè)通用的計(jì)算器工廠,根據(jù)用戶輸入的運(yùn)算符,生產(chǎn)出相應(yīng)的計(jì)算器對(duì)象,從而實(shí)現(xiàn)不同運(yùn)算的計(jì)算功能。
3. 實(shí)現(xiàn)方式
// 運(yùn)算器接口
interface Operator {
double calculate(double operand1, double operand2);
}
// 具體運(yùn)算器:加法運(yùn)算器
class AdditionOperator implements Operator {
@Override
public double calculate(double operand1, double operand2) {
return operand1 + operand2;
}
}
// 具體運(yùn)算器:減法運(yùn)算器
class SubtractionOperator implements Operator {
@Override
public double calculate(double operand1, double operand2) {
return operand1 - operand2;
}
}
// 具體運(yùn)算器:乘法運(yùn)算器
class MultiplicationOperator implements Operator {
@Override
public double calculate(double operand1, double operand2) {
return operand1 * operand2;
}
}
// 具體運(yùn)算器:除法運(yùn)算器
class DivisionOperator implements Operator {
@Override
public double calculate(double operand1, double operand2) {
if (operand2 == 0) {
throw new IllegalArgumentException("除數(shù)不能為零");
}
return operand1 / operand2;
}
}
// 簡(jiǎn)單工廠類
class CalculatorFactory {
public static Operator createOperator(String operatorType) {
switch (operatorType) {
case "+":
return new AdditionOperator();
case "-":
return new SubtractionOperator();
case "*":
return new MultiplicationOperator();
case "/":
return new DivisionOperator();
default:
throw new IllegalArgumentException("不支持的運(yùn)算符:" + operatorType);
}
}
}
// 調(diào)用代碼
public class XZ {
public static void main(String[] args) {
Operator operator1 = CalculatorFactory.createOperator("+");
System.out.println(operator1.calculate(1, 2));
Operator operator2 = CalculatorFactory.createOperator("-");
System.out.println(operator2.calculate(1, 2));
Operator operator3 = CalculatorFactory.createOperator("*");
System.out.println(operator3.calculate(1, 2));
Operator operator4 = CalculatorFactory.createOperator("/");
System.out.println(operator4.calculate(1, 2));
// Operator operator5 = CalculatorFactory.createOperator("%");
// System.out.println(operator5.calculate(1, 2));
// 執(zhí)行沒有的 Operator 就會(huì)報(bào)錯(cuò)
}
}
在這個(gè)示例中,Operator
是運(yùn)算器接口,定義了一個(gè) calculate()
方法來進(jìn)行運(yùn)算。AdditionOperator
、SubtractionOperator
、MultiplicationOperator
和 DivisionOperator
是具體運(yùn)算器類,分別表示加法運(yùn)算器、減法運(yùn)算器、乘法運(yùn)算器和除法運(yùn)算器,它們都實(shí)現(xiàn)了運(yùn)算器接口的方法。CalculatorFactory
是簡(jiǎn)單工廠類,它通過 createOperator()
方法來根據(jù)用戶輸入的運(yùn)算符類型,創(chuàng)建相應(yīng)的運(yùn)算器對(duì)象。
4. 類關(guān)系圖
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-XIXD3ZDl-1691793071649)(./assets/SimpleFactoryPattern.png)]
5. 應(yīng)用場(chǎng)景
- 當(dāng)需要根據(jù)不同的條件創(chuàng)建不同類型的對(duì)象時(shí),可以使用簡(jiǎn)單工廠模式。
- 簡(jiǎn)單工廠模式將對(duì)象的創(chuàng)建邏輯封裝在工廠類中,使得客戶端不需要知道具體的對(duì)象創(chuàng)建過程,只需要通過工廠類來獲取對(duì)象。
6. 易錯(cuò)點(diǎn)
- 在實(shí)現(xiàn)簡(jiǎn)單工廠模式時(shí),需要注意工廠類的職責(zé),它應(yīng)該負(fù)責(zé)根據(jù)條件創(chuàng)建相應(yīng)的對(duì)象,而不應(yīng)該承擔(dān)過多的業(yè)務(wù)邏輯。
7. 優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 將對(duì)象的創(chuàng)建邏輯封裝在工廠類中,使得客戶端不需要關(guān)心對(duì)象的具體創(chuàng)建過程,降低了客戶端和具體對(duì)象的耦合。
- 簡(jiǎn)單工廠模式可以通過工廠類來統(tǒng)一管理對(duì)象的創(chuàng)建,便于代碼的維護(hù)和管理。
缺點(diǎn)
- 如果需要添加新的運(yùn)算器類型,需要修改工廠類的代碼,這可能違反了開閉原則,導(dǎo)致工廠類的修改。
8. 總結(jié)
簡(jiǎn)單工廠模式是一種創(chuàng)建型設(shè)計(jì)模式,它通過一個(gè)工廠類來創(chuàng)建不同類型的對(duì)象,使得客戶端不需要關(guān)心對(duì)象的具體創(chuàng)建過程。簡(jiǎn)單工廠模式適用于當(dāng)需要根據(jù)不同的條件創(chuàng)建不同類型的對(duì)象時(shí)。在實(shí)現(xiàn)簡(jiǎn)單工廠模式時(shí),需要注意工廠類的職責(zé),它應(yīng)該負(fù)責(zé)根據(jù)條件創(chuàng)建相應(yīng)的對(duì)象,而不應(yīng)該承擔(dān)過多的業(yè)務(wù)邏輯。雖然簡(jiǎn)單工廠模式有一些優(yōu)點(diǎn),但也有一些缺點(diǎn),例如如果需要添加新的對(duì)象類型,可能需要修改工廠類的代碼,這可能違反了開閉原則。因此,在應(yīng)用簡(jiǎn)單工廠模式時(shí)需要權(quán)衡考慮,選擇合適的設(shè)計(jì)方案。
迪米特法則(LOD)
迪米特法則(Law Of Demeter,LOD),也被稱為最少知識(shí)原則(Least Knowledge Principle,LKP),是面向?qū)ο笤O(shè)計(jì)的一個(gè)重要原則。它指導(dǎo)我們?cè)谠O(shè)計(jì)類和模塊時(shí)要盡量減少對(duì)象之間的耦合,讓類之間的關(guān)系盡可能簡(jiǎn)單。迪米特法則的核心思想是一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有盡可能少的了解,它只與其直接的朋友(成員變量、方法的輸入?yún)?shù)、方法返回值)發(fā)生交互,而不與間接的朋友發(fā)生交互。
雖然迪米特法則在面向?qū)ο笤O(shè)計(jì)中是一個(gè)重要的原則,但并不是所有設(shè)計(jì)模式都明確地使用了它。有些設(shè)計(jì)模式確實(shí)能夠很好地體現(xiàn)迪米特法則的思想,例如外觀模式、中介者模式等,它們都能夠通過封裝和簡(jiǎn)化對(duì)象之間的交互,減少耦合。但并不是所有設(shè)計(jì)模式都顯式地遵循迪米特法則。
有以下幾個(gè)原因可能解釋為什么不是所有設(shè)計(jì)模式都使用了迪米特法則:
- 設(shè)計(jì)模式的目的多樣性:設(shè)計(jì)模式是為了解決不同的設(shè)計(jì)問題而產(chǎn)生的,每種設(shè)計(jì)模式都有其特定的目的和應(yīng)用場(chǎng)景。并不是所有的設(shè)計(jì)問題都可以通過減少對(duì)象之間的交互來解決,因此不是所有設(shè)計(jì)模式都會(huì)涉及迪米特法則。
- 原則沖突:在實(shí)際的設(shè)計(jì)中,有時(shí)可能會(huì)存在多個(gè)設(shè)計(jì)原則之間的沖突,需要在不同的情況下進(jìn)行權(quán)衡取舍。有時(shí)為了滿足其他設(shè)計(jì)原則,可能會(huì)導(dǎo)致迪米特法則無法完全滿足。
- 上下文依賴:某些設(shè)計(jì)模式可能需要多個(gè)對(duì)象之間的密切合作,這可能導(dǎo)致它們之間的交互較多,而迪米特法則要求盡量減少對(duì)象之間的交互。在這種情況下,可能需要權(quán)衡考慮,不一定能完全符合迪米特法則。
雖然不是所有設(shè)計(jì)模式都直接遵循迪米特法則,但迪米特法則仍然是一個(gè)有價(jià)值的原則,可以在設(shè)計(jì)中作為參考指導(dǎo)。在實(shí)際設(shè)計(jì)中,我們應(yīng)該綜合考慮各種設(shè)計(jì)原則和模式,以便得到合適的解決方案。每個(gè)設(shè)計(jì)模式都有其獨(dú)特的用途和優(yōu)勢(shì),我們應(yīng)該根據(jù)具體的情況選擇合適的設(shè)計(jì)模式來解決問題。
設(shè)計(jì)模式拓展
設(shè)計(jì)模式是一種用于解決特定問題的通用解決方案,它們是經(jīng)過驗(yàn)證的、被廣泛接受的最佳實(shí)踐。除了常見的設(shè)計(jì)模式,還有一些拓展和衍生的設(shè)計(jì)模式,以及一些設(shè)計(jì)原則和編程技巧可以進(jìn)一步優(yōu)化和擴(kuò)展設(shè)計(jì)模式的應(yīng)用。
- 行為型設(shè)計(jì)模式的拓展:除了前面提到的行為型設(shè)計(jì)模式(策略模式、觀察者模式、狀態(tài)模式等),還有一些其他行為型設(shè)計(jì)模式,如備忘錄模式、命令模式、解釋器模式等。
- 創(chuàng)建型設(shè)計(jì)模式的拓展:創(chuàng)建型設(shè)計(jì)模式(工廠方法模式、抽象工廠模式、建造者模式等)也有一些拓展,如單例模式的各種實(shí)現(xiàn)方式(懶漢式、餓漢式、雙重檢查鎖等)。
- 結(jié)構(gòu)型設(shè)計(jì)模式的拓展:結(jié)構(gòu)型設(shè)計(jì)模式(適配器模式、裝飾器模式、代理模式等)也有一些相關(guān)的模式,如橋接模式、組合模式等。
- 并發(fā)設(shè)計(jì)模式:并發(fā)編程中有一些特定的設(shè)計(jì)模式,用于解決多線程和并發(fā)訪問的問題,如鎖、信號(hào)量、阻塞隊(duì)列等。
- 函數(shù)式編程的設(shè)計(jì)模式:隨著函數(shù)式編程的興起,也出現(xiàn)了一些與函數(shù)式編程相關(guān)的設(shè)計(jì)模式,如柯里化、函數(shù)組合、惰性求值等。
- 架構(gòu)模式:除了針對(duì)具體問題的設(shè)計(jì)模式,還有一些面向整個(gè)軟件系統(tǒng)架構(gòu)的設(shè)計(jì)模式,如分層架構(gòu)、微服務(wù)架構(gòu)等。
- 響應(yīng)式編程模式:響應(yīng)式編程是一種面向異步數(shù)據(jù)流和事件驅(qū)動(dòng)的編程范式,它在處理事件和數(shù)據(jù)流時(shí)使用了一些特定的設(shè)計(jì)模式,如觀察者模式和迭代器模式。
- 數(shù)據(jù)訪問設(shè)計(jì)模式:用于解決數(shù)據(jù)訪問層的設(shè)計(jì)問題,如數(shù)據(jù)訪問對(duì)象模式(DAO)、倉儲(chǔ)模式等。
這些拓展和衍生的設(shè)計(jì)模式都是在特定場(chǎng)景下為了解決特定問題而產(chǎn)生的,它們豐富了設(shè)計(jì)模式的應(yīng)用范圍,并提供了更多的解決方案供開發(fā)者選擇。在實(shí)際應(yīng)用中,我們需要根據(jù)具體的問題和需求選擇合適的設(shè)計(jì)模式,或者結(jié)合多種設(shè)計(jì)模式來構(gòu)建出更復(fù)雜、更靈活的系統(tǒng)。同時(shí),也應(yīng)該注意不要濫用設(shè)計(jì)模式,只有在合適的場(chǎng)景下使用合適的設(shè)計(jì)模式才能真正發(fā)揮它們的優(yōu)勢(shì)。文章來源:http://www.zghlxwxcb.cn/news/detail-651632.html
玄子Share 設(shè)計(jì)模式 GOF 全23種 + 七大設(shè)計(jì)原則 8.2文章來源地址http://www.zghlxwxcb.cn/news/detail-651632.html
到了這里,關(guān)于創(chuàng)建型模式 (Creational Patterns) 玄子Share 設(shè)計(jì)模式 GOF 全23種 + 七大設(shè)計(jì)原則的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!