1. 程式人生 > >設計模式之基礎模式概覽

設計模式之基礎模式概覽

cnblogs 組件 解析器 scrip 場景 不同的 返回 apt jid

概述

設計模式是實現特定需求的接近代碼層面的設計套路,通常用於梳理和表達對象之間較為復雜的依賴和交互關系,將錯綜復雜的容易膨脹的難以理解和擴展的條件判斷邏輯解開成一系列對象的清晰可理解的易擴展的交互結構。不同的設計模式之間有一些形式上的相似點,區分在於關註點不同。

設計模式是軟件設計的入門指南,其主要理念是: 面向接口的編程,組合與委托優先於繼承。理解設計模式的關鍵點:關註點及目標用途、協作對象、靜態結構及動態交互。

基礎模式

常用的基礎設計模式有:

工廠模式

  • 工廠模式(FactoryMethod):根據不同條件為客戶端創建實現相同接口和功能的實例,而客戶端使用的是統一的功能接口。有點類似策略模式,不過工廠模式創建的是具備狀態和行為的實例,而策略模式則是對行為和算法建模。典型示例有 Spring Bean 工廠。 很多模式也需要聯合工廠模式,比如策略模式、模板方法模式等。

單例模式

  • 單例模式(Singleton):為某類服務創建唯一的全局訪問點。多線程環境下需考慮並發創建問題,可使用枚舉。典型示例有 Spring Component/Service 。

生成器模式

  • 生成器模式(Builder):復雜對象的創建,需要多個步驟或組合多個子部件完成,並且在這些步驟或組件完成之前,不允許該實例的生成。通常會私有化構造器,在構造的每一步驟中會設置某些屬性並返回其自身,便於鏈式調用,提供一個build方法生成滿足某種實例創建契約的最終實例。比如汽車制造,就適用生成器模式。

可參閱 lombok 庫的 @Builder 註解。

抽象工廠模式

  • 抽象工廠模式(AbstractFactory): 系統含有多個相互協作的不同功能和特性的組件,每個組件可定制為不同的種類和風格。抽象工廠為每個組件的創建提供相對應的抽象工廠的創建接口,而由具體的工廠實現對應的組件創建接口。即有:XXXComponent 對應 XXXAbstractFactory , XXXAbstractFactory 含有一個 createXXXComponent 的創建接口,這裏 XXXComponent, XXXAbstractFactory 都是接口而不是實現。抽象工廠用於創建協作的多個組件實例的接口骨架。

原型模式

  • 原型模式(Prototype): 從現有對象實例快速生成和定制化對象實例,而不需要創建大量子類。原型模式特別適合於定制化。比如,現有一個房間對象,要創建含有炸彈的房間對象;這些房間對象的房間屬性都是一樣的,而這些炸彈可能是不同種類,也可能是相同種類只是顏色不同,使用普通的繼承結構和初始化操作會產生大量的相同的賦值代碼。此時使用原型模式非常恰當。通過一個含有普通炸彈的房間對象作為原型進行克隆,然後設置炸彈的種類和屬性即可。原型模式使用有兩點:需要一個原型管理器進行原型註冊和查找;根據場景正確地實現淺拷貝和深拷貝。為原型靜態或動態地增加屬性和行為,可以輕易地為所有從該原型衍生的對象添加屬性和行為。Javascript語言提供了原型機制。

適配器模式

  • 適配器模式(Adapter):復用現有類或對象的功能,實現客戶端需要的接口。有類適配器和對象適配器兩種。類適配器繼承現有類,可以重新定義部分行為;對象適配器使用現有類的對象實例並委托實現給該對象,可靈活使用多個現有對象。通常使用對象適配器。

組合模式

  • 組合模式(Composite): 具有層次性結構的單個對象與組合對象具有一致的接口,客戶端能夠使用統一的接口操作局部和整體。樹形組件是典型示例。

可參閱: “設計模式之組合模式:實現復合搜索條件構建”

外觀模式

  • 外觀模式(Facade):為復雜子系統提供簡單易用的接口,屏蔽實現的復雜性。庫的API,Java的正則對象(Compiler,Matcher)是典型的外觀模式應用。

裝飾器模式

  • 裝飾器模式(Decorator):具有相同接口的對象可以在運行時動態組合成具有復合行為的對象。可以在運行時為現有對象動態添加任意復雜的額外行為。典型示例有 JavaIO框架。函數式編程是實現裝飾器模式的強大機制。

可參閱:“Java函數接口實現函數組合及裝飾器模式” ,“使用IntelljIDEA生成接口的類繼承圖及裝飾器模式”

代理模式

  • 代理模式(Proxy): 為對象或服務提供間接訪問機制。提供間接訪問的原因可能有:隱藏源對象或源服務的部署細節(遠程代理);源對象創建開銷很大,只有需要的時候才創建(虛代理);訪問源對象需要某種權限或同步互斥(保護代理);需要為訪問源對象和源服務增加額外的行為(智能代理)。代理對象與源對象通常有一致的接口,並持有源對象的引用。

橋接模式

  • 橋接模式(Bridge):抽象部分與實現部分各具有獨立的繼承層次結構分開變化發展,使用橋接器將抽象繼承層次與實現繼承層次連接起來,實現並不直接繼承抽象類,而是抽象類持有實現類的引用。通常適用於這樣的場景:創建一個標準協議的接口框架,而接口框架的實現可以有多種選擇,客戶端可以根據需要選擇不同的實現。橋接器通常與抽象工廠模式、單例模式組合使用。典型應用有JDBC的接口與實現、日誌API接口與實現。

享元模式

  • 享元模式(Flyweight):大量不可變小對象的共享與管理。比如基礎類型裏的常用的26個字符對象、256個小整數對象、化學元素及原子等。可使用緩存技術實現。為了盡可能節省內存開銷,需要識別享元對象中的外部狀態並從中移除,使得享元對象的共享達到最大化。享元模式可與抽象工廠模式、組合模式聯合使用。應用示例有使用面向對象技術創建的文檔編輯器。

模板方法模式

  • 模板方法模式(TemplateMethod):預先定義處理流程,對於流程中某些環節的具體處理留給具體業務去完成。模板方法模式應指明哪些是鉤子操作(可選重定義的,有默認實現),哪些是抽象操作(必須重定義的,沒有默認實現)。對於抽象操作,可以使用統一命名前綴來識別,比如mustDoXXX. 典型示例有 Java容器框架。

可參閱:“設計模式之模板方法模式:實現可擴展性設計(Java示例)”

策略模式

  • 策略模式(Strategy):為特定任務提供多種實現算法,並在不同場景下可靈活切換而對客戶端透明。比如批量拉取數據的順序策略(簡單而略慢)以及並發策略(快速而略復雜)。使用策略模式時,客戶端可持有策略實現對象的接口或者策略實現對象的模板接口參數。具體應用例子有排序,提供多種排序策略,客戶端可根據需要采用所需要的排序實現(簡單性、穩定性、性能、內存占用、多關鍵字、內存排序、文件排序)。

可參閱:“設計模式之策略模式:分離不同實現(Java示例)”

觀察者模式

  • 觀察者模式(Observer):每個對象都有一系列觀察者,當對象發生更新時推送更新給觀察者,由觀察者決定具體行為。通常引申為訂閱-消費模式。GUI應用是觀察者模式的典型應用之一。

可參閱: “設計模式之觀察者模式:實現配置更新實時推送”

職責鏈模式

  • 職責鏈模式(ResponsibiltyChain):將能夠處理某種請求的多個對象串聯成一條處理鏈,請求沿著處理鏈傳遞給這些對象,對請求的發送者隱藏處理請求的實現細節(請求的發送者不需要知道誰真正處理這個請求)。 責任鏈上的請求處理對象可以在運行時動態增減。責任鏈的實現中,鏈的構造和請求的傳遞既可以使用全局控制器來配置、生成和控制(集中式策略),也可以通過鏈上的對象來負責引用和傳遞(分散式策略)。需要構造兩種接口:請求接口和請求處理對象的接口,而請求處理對象則需要實現請求接口。請求處理對象的順序也值得斟酌,通常是從特殊到普遍的順序。異常捕獲和處理機制即是職責鏈模式的具體應用例子之一。

命令模式

  • 命令模式(Command):將行為封裝到通用接口中,通過命令調用。類似回調接口,可以使用函數式編程實現。具體應用例子有JDBCTemplate。

可參閱: “統計方法運行時間【Java實現】”

叠代器模式

  • 叠代器模式(Iterator):為復雜的組合對象結構返回叠代器,安全訪問其中的元素,隱藏復雜的結構細節。典型示例有Java容器的叠代器,JDBC的ResultSet。

狀態模式

  • 狀態模式(State): 一個對象具有多種狀態,其某種復雜行為取決於狀態及狀態變遷(代碼實現通常是一個大的Switch-If語句)。此時,可以單獨將狀態及行為抽離出來建模,並將對象的行為委托狀態對象完成。若狀態行為比較簡單,可以使用具有行為的枚舉或表來實現;若狀態行為比較復雜,則需要使用狀態抽象類及具體狀態子類來實現。狀態對象可持有對象的引用,便於訪問所需要的信息。狀態子類沒有實例屬性,可以實現為單例類。常見的應用有:TCP連接狀態管理、虛擬機狀態管理、訂單狀態管理。

中介者模式

  • 中介者模式(Mediator):有多個基礎服務方,多個業務方;每個業務方都有自己需要定制化的東西。如果所有業務方直接與各個基礎服務方打交道,會導致“服務方-業務方”的依賴關系激增(乘法關系),交互也變得復雜。引入中介者對象作為服務方和業務方的調度調控,每個基礎服務方和業務方只需要與中介者交互,而不需要知道具體的服務方和業務方。中介者對象將交互行為集中化,簡化了依賴關系數量(加法關系)。 中介者對象在應用組織架構中俗稱“中臺”。

解釋器模式

  • 解釋器模式(Interpret):如果特定問題可以使用一種簡單的語言來描述,那麽可以定義一種文法,以及對應的解釋器。將問題的求解歸結為根據文法構造句子,然後使用解析器來解釋句子生成結果。適用於領域語言設計和實現。典型例子有用於字符串匹配的正則表達式解析以及JSON解析。

可參閱: “Java實現圖案打印: 記法與解釋器”

訪問模式

  • 訪問模式(Visitor):一個復雜的復合對象含有多個子對象 A,B,C, 對於每個子對象都需要定義操作 op1, op2, op3, ... , opN ,而每個子對象的操作 opi 都可能是不一樣的。 全部操作的定義放在這個復合對象裏,將使得這個復合對象異常的龐大臃腫。使用訪問器模式,可以將這些操作抽離出來。每種操作都是一個訪問器ConcreteVisitor,可以定義訪問接口visitA,visitB,visitC ; 每個子對象以及該復合對象都有一個 accept(Visit) 的方法。復合對象的 accept 實現將委托給遍歷子對象的 accept 。 Visitor 主要用於為復合對象定義可擴展的新操作。當定義一個新操作時,只需要增加一個新的ConcreteVisitor,而不需要改動現有的其他類。如果子對象變化頻繁,那麽每個 Visitor 都要增加一個 visitorX 的方法,Visitor模式就不適用了。

備忘錄模式

  • 備忘錄模式(Memento):歷史狀態存儲、撤銷與回退。

模式組合

組合是力量之源。每個設計模式都有某個關註點,而這些關註點是相互協作的;具有協作關系的模式也是可以組合的。可以閱讀《面向模式的軟件架構》系列學習基礎模式如何組合而得到更大的實用架構模式。這裏引用《設計模式:可復用面向對象軟件的基礎》的圖:
技術分享圖片

模式示例

可參考個人工程 ALLIN 下的 src/main/java/zzz/study/patterns 包下的文件。

設計模式之基礎模式概覽