23種設計模式
- 🎯 創建型設計模式
- 📌 抽象工廠(Abstract Factory) 設計模式
- 📌 工廠方法(Factory Method)設計模式
- 📌 單例(Singleton)設計模式
- 📌 生成器(Builder)設計模式
- 📌 原型(Prototype)設計模式
- 🎯 結構型設計模式
- 📌 適配器(Adapter)設計模式
- 📌 橋接(Bridge)設計模式
- 📌 組合(Composite)設計模式
- 📌 裝飾器(Decorator)設計模式
- 📌 外觀(Facade)設計模式
- 📌 享元(Flyweight)設計模式
- 📌 代理(Proxy)設計模式
- 🎯 行為型設計模式
- 📌 責任鏈(Chain of Responsibility)設計模式
- 📌 命令(Command)設計模式
- 📌 解釋器(Interpreter)設計模式
- 📌 迭代器(Iterator)設計模式
- 📌 中介者(Mediator)設計模式
- 📌 備忘錄(Memento)設計模式
- 📌 觀察者(Observer)設計模式
- 📌 狀態(State)設計模式
- 📌 策略(Strategy)設計模式
- 📌 模板方法(Template Method)設計模式
- 📌 訪問者(Visitor)設計模式
針對軟件設計師考試中設計模式題型,這篇文章對23種設計模式作總結
🎯 創建型設計模式
📌 抽象工廠(Abstract Factory) 設計模式
點擊跳轉:抽象工廠模式代碼實例(Java)
💡 意圖
提供一個創建一系列相關或相互依賴的接口,而無需指定他們具體的類
💡 圖例
圖中綠色虛線是接口實現關系,白色虛線為實例化創建
💡 適用場景
-
一個系統要獨立于它的產品的創建,組合和表示時;
-
一個系統要由多個產品系列中的一個來配置時;
-
需要強調一系列相關的產品對象的設計以便進行聯合使用時;
-
提供一個產品類庫,而只想顯示它們的接口而不是實現時。
📌 工廠方法(Factory Method)設計模式
點擊跳轉:工廠方法模式代碼實例(Java)
💡 意圖
提供一個創建對象的接口,但由子類決定要實例化的具體類。工廠方法使得類的實例化延遲到子類。
💡 圖例
圖中綠色虛線是接口實現關系,l藍色實線表示抽象類繼承,白色虛線為實例化創建
💡 適用場景
-
當一個類無法預見它所需要的對象的具體類型時,使用工廠方法模式。
-
當一個類希望將創建對象的責任委托給子類,以便于擴展時。
-
當需要避免在代碼中直接依賴具體類,而是通過抽象接口或基類進行操作時。
-
當一組相關的產品需要動態創建,但只希望暴露其抽象接口時。
📌 單例(Singleton)設計模式
點擊跳轉:單例模式代碼實例(Java)
💡 意圖
確保一個類只有一個實例,并提供全局訪問點來獲取該實例。單例模式常用于管理共享資源或需要全局唯一對象的場景。
💡 圖例
SingletonPattern沒有實例化,只能通過getInstance()訪問
💡 適用場景
-
當一個類只能有一個實例時,如配置管理器、日志對象、線程池等。
-
當需要全局訪問點時,如訪問數據庫連接池或緩存管理器。
-
避免對象創建時浪費資源,如只需要一個共享實例而不需要重復創建時。
-
當類的實例化和使用分離時,可以通過延遲實例化來優化性能。
📌 生成器(Builder)設計模式
點擊跳轉:生成器模式代碼實例(Java)
💡 意圖
將一個復雜對象的構建過程與其表示分離,使得同樣的構建過程可以創建不同的表示。生成器模式允許通過逐步構建的方式,靈活創建復雜對象。
💡 圖例
💡 適用場景
-
當對象的構建過程復雜,涉及多個步驟時,如構建一個多層次的復雜對象。
-
當需要創建不同表現形式的復雜對象時,但構建過程相同時。
-
當需要在不同環境下構建不同的產品時,如不同的操作系統或數據庫配置等。
-
當客戶端只需要關心最終對象的類型,而不關心構建過程時,可以通過生成器模式提供更好的封裝和靈活性。
📌 原型(Prototype)設計模式
點擊跳轉:原型模式代碼實例(Java)
💡 意圖
通過復制現有的對象來創建新的對象,而不是通過實例化新對象。原型模式允許在運行時動態地克隆對象,從而簡化對象的創建過程,尤其適用于復雜對象的創建。
💡 圖例
💡 適用場景
-
當創建對象的成本較高,且相似對象可以通過克隆來獲得時。
-
當需要大量相似對象,但是其細節有所不同時,可以通過原型模式創建這些對象。
-
當類的構造過程復雜,但可以通過克隆現有對象來快速創建新實例時。
-
當對象的狀態或行為需要從現有對象進行復制,而不需要重新構造時。
🎯 結構型設計模式
📌 適配器(Adapter)設計模式
點擊跳轉:適配器模式代碼實例(Java)
💡 意圖
將一個類的接口轉換成客戶端所期待的另一個接口,使得原本接口不兼容的類能夠一起工作。適配器模式使得不同接口之間可以協同工作,通常用于連接新舊系統。
💡 圖例
💡 適用場景
-
當你希望通過現有的接口來訪問舊系統中的功能,但這些功能的接口和新的系統不兼容時。
-
當需要使用一些現有的類,但它們的接口不符合要求時,可以通過適配器模式使其兼容。
-
當系統中多個類的接口不一致,且這些類需要協同工作時。
-
當你需要讓類具有更靈活的接口,能與不同的外部接口交互時。
📌 橋接(Bridge)設計模式
點擊跳轉:橋接模式代碼實例(Java)
💡 意圖
將抽象部分與實現部分分離,使得二者可以獨立變化。橋接模式通過引入橋接接口,將抽象部分與實現部分解耦,從而在不改變客戶端代碼的前提下,改變或擴展系統的實現。
💡 圖例
💡 適用場景
-
當需要將抽象部分與其實現部分解耦,使得二者可以獨立擴展時。
-
當一個類存在多個變化維度,且每個維度都可能變化時,橋接模式可以減少子類的數量。
-
當需要在不同的操作系統或設備之間共享功能實現時,通過橋接模式實現對不同平臺的支持。
-
當類的繼承結構較為復雜,導致子類眾多時,橋接模式有助于簡化設計。
📌 組合(Composite)設計模式
點擊跳轉:組合模式代碼實例(Java)
💡 意圖
將對象組合成樹形結構以表示“部分-整體”的層次結構。組合模式讓客戶端可以統一地對待單個對象和對象集合,通常用于表示樹形結構,如文件系統或組織結構。
💡 圖例
💡 適用場景
-
當需要表示“部分-整體”層次結構時,如組織架構、文件目錄等。
-
當客戶端需要統一地處理單個對象和對象集合時,通過組合模式避免區分對象和容器。
-
當對象數量不確定且層次結構復雜時,組合模式可以簡化操作。
-
當你希望構建一個遞歸樹形結構時,如樹形菜單、圖形組件等。
📌 裝飾器(Decorator)設計模式
點擊跳轉:裝飾器模式代碼實例(Java)
💡 意圖
動態地為對象添加新的功能,而不影響其原有結構。裝飾器模式通過將對象包裝在一個或多個裝飾器中,增強其功能,而無需修改原始類。
💡 圖例
💡 適用場景
-
當不希望通過繼承來擴展類的功能時,可以使用裝飾器模式動態地增加行為。
-
當需要在運行時為對象添加額外功能時,裝飾器模式提供比繼承更靈活的解決方案。
-
當希望用多個不同的功能裝飾同一個對象時,裝飾器模式允許自由組合不同的裝飾功能。
-
當系統需要遵循開閉原則(OCP),即對擴展開放、對修改封閉時,裝飾器模式是理想選擇。
📌 外觀(Facade)設計模式
點擊跳轉:外觀模式代碼實例(Java)
💡 意圖
為子系統中的一組接口提供一個統一的接口,外觀模式定義了一個高層接口,使得子系統更容易使用。它主要用于簡化復雜系統的訪問,提高代碼的可讀性和維護性。
💡 圖例
💡 適用場景
-
當系統過于復雜,且外部調用者只需要關注高層邏輯時,外觀模式可以提供簡單的訪問方式。
-
當多個子系統需要被統一管理時,外觀模式可以減少直接訪問子系統的復雜性。
-
當希望對子系統進行解耦,以便日后修改子系統時,外觀模式可以隱藏子系統的細節。
-
當需要提供一個一致的接口,以屏蔽多個子系統的不同實現時,可以使用外觀模式。
📌 享元(Flyweight)設計模式
點擊跳轉:享元模式代碼實例(Java)
💡 意圖
通過共享對象來減少內存使用,以支持大量細粒度對象的高效使用。享元模式避免了創建重復對象,從而提高性能,尤其適用于資源受限的環境。
💡 圖例
💡 適用場景
-
當系統中存在大量相似對象,并且會消耗大量內存時,享元模式可以減少對象數量。
-
當對象的大部分狀態是相同的,僅少部分狀態有所變化時,可以將不變部分作為享元共享。
-
當創建對象的開銷較大,且需要優化性能時,享元模式能夠減少對象創建成本。
-
當系統需要支持大量對象但受限于內存資源時,享元模式提供了一種共享機制。
📌 代理(Proxy)設計模式
點擊跳轉:代理模式代碼實例(Java)
💡 意圖
為某個對象提供一個代理,以控制對該對象的訪問。代理模式用于在訪問對象前增加額外的邏輯,例如權限控制、懶加載、日志記錄、遠程訪問等。
💡 圖例
💡 適用場景
-
遠程代理(Remote Proxy)
: 當需要訪問遠程對象時,代理模式可以封裝網絡通信細節,例如 RMI(遠程方法調用)。 -
虛擬代理(Virtual Proxy)
: 當對象創建開銷較大時,代理可以延遲對象的初始化(懶加載)。 -
保護代理(Protection Proxy)
: 當需要控制對對象的訪問權限時,例如不同用戶權限訪問不同的功能。 -
緩存代理(Cache Proxy)
: 代理對象可以存儲訪問的結果,避免重復計算,提高性能。 -
智能引用代理(Smart Reference)
: 代理在訪問對象時附加額外操作,例如記錄日志或統計訪問次數。
🎯 行為型設計模式
📌 責任鏈(Chain of Responsibility)設計模式
點擊跳轉:責任鏈模式代碼實例(Java)
💡 意圖
將多個處理者按順序連接成一條鏈,每個處理者都可以處理請求或將其傳遞給下一個處理者。責任鏈模式避免了請求發送者與接收者之間的直接耦合,使請求處理更加靈活。
💡 圖例
💡 適用場景
-
當請求需要被多個對象處理時,可以使用責任鏈模式動態決定處理者的順序。
-
當請求的處理邏輯需要靈活擴展時,責任鏈模式允許動態增加或修改處理者。
-
當希望降低請求發送者與接收者的耦合度時,責任鏈模式使得請求者不需要關心具體的處理者。
-
當有多個處理者可以處理請求,但具體由誰處理在運行時決定時,責任鏈模式提供了一種靈活的解決方案。
📌 命令(Command)設計模式
點擊跳轉:命令模式代碼實例(Java)
💡 意圖
將請求封裝成對象,以便使用不同的請求、隊列或者日志來參數化對象。命令模式允許請求的發送者和接收者解耦,并支持操作的撤銷(Undo)和恢復(Redo)。
💡 圖例
💡 適用場景
-
當需要將請求封裝為對象,以支持撤銷(Undo)和恢復(Redo)功能時,命令模式能夠很好地管理請求。
-
當系統需要對請求排隊、記錄日志或支持事務時,命令模式可以靈活處理這些需求。
-
當需要將請求的發送者和執行者解耦時,命令模式提供了一個中間層,使兩者不直接交互。
-
當系統需要支持宏命令(批量命令)時,命令模式可以組合多個命令并統一執行。
📌 解釋器(Interpreter)設計模式
點擊跳轉:解釋器模式代碼實例(Java)
💡 意圖
定義一個語言的語法表示,并提供一個解釋器來處理該語言的句子。解釋器模式用于設計編譯器、表達式計算器、規則引擎等,以解析和執行特定的語法規則。
💡 圖例
💡 適用場景
-
當需要解析和執行特定語言的語法規則時,解釋器模式能夠將復雜的語法解析為對象結構。
-
當存在特定的業務規則需要頻繁更改或擴展時,解釋器模式可以提供靈活的規則定義方式。
-
當系統需要支持不同的表達式計算時,如數學計算、邏輯運算、SQL 解析等,解釋器模式是合適的選擇。
-
當要構造一個簡單的編譯器或解釋器時,可以使用解釋器模式解析語法樹并執行相應的操作。
📌 迭代器(Iterator)設計模式
點擊跳轉:迭代器模式代碼實例(Java)
💡 意圖
提供一種方法順序訪問集合對象中的元素,而不暴露其內部表示。迭代器模式使得遍歷不同集合結構(如數組、鏈表、樹等)時可以使用統一的方式,并且解耦了遍歷算法與集合對象的實現。
💡 圖例
💡 適用場景
-
當需要遍歷集合對象,但不希望暴露集合的內部結構時,迭代器模式可以提供一個統一的訪問方式。
-
當需要支持多種遍歷方式(正序、倒序、跳躍等)時,迭代器模式允許自定義迭代邏輯。
-
當希望對不同類型的集合結構(如數組、鏈表、哈希表等)使用相同的遍歷接口時,迭代器模式提供了解決方案。
-
當多個對象需要順序訪問集合對象時,迭代器模式可以確保遍歷過程的獨立性和一致性。
📌 中介者(Mediator)設計模式
點擊跳轉:中介者模式代碼實例(Java)
💡 意圖
定義一個中介對象,封裝多個對象之間的交互,使對象之間不再相互引用,而是通過中介者進行通信。中介者模式降低了對象之間的耦合度,使得系統更加可擴展和維護。
💡 圖例
💡 適用場景
-
當對象之間存在復雜的交互關系時,中介者模式可以簡化對象的相互依賴,避免對象之間形成網狀結構。
-
當多個對象之間的交互需要統一管理時,中介者模式可以提供一個中心化的管理機制。
-
當對象之間的交互需要動態變化時,中介者模式可以讓交互邏輯集中在一個類中,便于修改和擴展。
-
當需要減少類之間的耦合,提高代碼的可維護性時,中介者模式是一個不錯的選擇。
📌 備忘錄(Memento)設計模式
點擊跳轉:備忘錄模式代碼實例(Java)
💡 意圖
備忘錄模式在不暴露對象內部狀態的情況下,保存對象的狀態,以便在需要時恢復到先前的狀態。它允許在不破壞封裝的情況下保存和恢復對象的狀態,適用于需要撤銷或恢復功能的場景。
💡 圖例
💡 適用場景
-
當系統需要提供撤銷(Undo)或恢復(Redo)功能時,備忘錄模式能夠存儲對象的歷史狀態。
-
當對象狀態變化頻繁,且需要隨時恢復到某個歷史狀態時,備忘錄模式可以有效管理和恢復這些狀態。
-
當需要在不破壞封裝的情況下,保存對象的狀態時,備忘錄模式允許保存對象的狀態,而不會暴露其實現細節。
-
當需要在某個操作執行后,能夠恢復到先前的狀態時,備忘錄模式非常適用。
📌 觀察者(Observer)設計模式
點擊跳轉:觀察者模式代碼實例(Java)
💡 意圖
定義了一種一對多的依賴關系,使得每當一個對象的狀態發生改變時,所有依賴于它的對象都會自動收到通知并更新。觀察者模式通常用于事件監聽、廣播通信等場景,它解耦了被觀察者和觀察者之間的關系。
💡 圖例
💡 適用場景
-
當一個對象的狀態變化需要影響其他對象時,且不希望被觀察者和觀察者之間產生過強的耦合時,觀察者模式是理想的解決方案。
-
當多個觀察者對象需要響應同一事件的變化時,觀察者模式能自動通知所有相關的觀察者。
-
當需要提供事件驅動機制時,例如在 GUI 應用程序中,當按鈕被點擊時,需要通知多個組件進行相應的處理。
-
當一個對象的狀態變化需要同時通知多個不同類型的對象時,觀察者模式能夠提供靈活的通知機制。
📌 狀態(State)設計模式
點擊跳轉:狀態模式代碼實例(Java)
💡 意圖
允許一個對象在其內部狀態改變時改變其行為,看起來就像是改變了類。狀態模式通過將不同的狀態封裝成獨立的類,使得對象的行為隨著狀態的不同而變化,避免了大量的條件語句。
💡 圖例
💡 適用場景
-
當一個對象的行為依賴于其狀態,并且在運行時其狀態可能會改變時,狀態模式可以更好地組織和管理這些行為。
-
當對象的行為隨著狀態的改變而變化,且使用條件語句處理這種變化顯得繁瑣和難以維護時。
-
當系統中存在多種狀態轉換邏輯,并且每個狀態下的行為都需要清晰分離時,狀態模式非常適合。
-
當希望避免多個條件判斷語句(如 if-else 或 switch)時,狀態模式可以將每個狀態的行為獨立封裝,減少復雜度。
📌 策略(Strategy)設計模式
點擊跳轉:策略模式代碼實例(Java)
💡 意圖
定義一系列的算法,將每一個算法封裝起來,并使它們可以互換。策略模式使得算法的變化獨立于使用算法的客戶。通過定義策略接口和多個具體的策略實現,策略模式允許客戶端在運行時選擇不同的算法或行為。
💡 圖例
💡 適用場景
-
當系統中存在多個算法(策略)且這些算法可以相互替換時,策略模式提供了一個靈活的方式來封裝和選擇不同的算法。
-
當需要根據不同的環境或條件來選擇不同的行為時,策略模式能夠幫助分離選擇邏輯和具體算法。
-
當系統中有很多類似的條件語句(如 if-else 或 switch),而這些條件語句負責選擇不同算法時,策略模式可以讓條件邏輯更加清晰并易于擴展。
-
當算法或行為頻繁變化時,策略模式讓這些變化更加容易控制和擴展,避免對客戶代碼的修改。
📌 模板方法(Template Method)設計模式
點擊跳轉:模板方法模式代碼實例(Java)
💡 意圖
定義一個操作中的算法骨架,將一些步驟的實現延遲到子類中。模板方法使得子類可以在不改變算法結構的情況下重新定義算法中的某些特定步驟。它主要用于定義一個不變的算法結構,并允許子類去實現其中的某些可變部分。
💡 圖例
💡 適用場景
-
當一個算法中有一些不變的步驟,而某些步驟可以由子類改變時,模板方法模式非常適用,它將不變的部分提取到父類中。
-
當多個子類有共同的算法結構,但部分細節需要不同實現時,可以通過模板方法模式來定義統一的框架,并讓子類提供不同的實現。
-
當你想在不修改類的情況下,擴展現有算法時,模板方法模式可以通過子類重寫方法來進行擴展。
-
當一個操作的步驟是固定的,而某些步驟需要定制化時,模板方法模式幫助將步驟的共同部分和特定實現區分開。
📌 訪問者(Visitor)設計模式
點擊跳轉:訪問者模式代碼實例(Java)
💡 意圖
將數據結構與操作數據的行為分離,使得操作數據的行為可以獨立于數據結構變化而變化。訪問者模式允許你在不改變對象結構的前提下,增加新的操作。它通常用于需要對一組對象執行一系列操作的場景。
💡 圖例
💡 適用場景
-
當需要對一組對象進行操作,但不希望修改對象結構時,訪問者模式通過將操作邏輯從對象中抽離出來實現了操作與數據的解耦。
-
當需要在系統中增加新的操作時,訪問者模式能夠通過添加新的訪問者來擴展系統,而無需修改已有的元素類。
-
當需要對元素結構中的對象進行復雜的操作,并且這些操作涉及不同類型的元素時,訪問者模式能夠簡化操作的管理和擴展。
-
當你希望將操作集中管理,而不是讓操作邏輯分散在不同的類中時,訪問者模式可以幫助集中管理訪問操作。
創作不易,不妨點贊、收藏、關注支持一下,各位的支持就是我創作的最大動力??