天天看點

設計模式GOF23之第二回

1. 概述

結構型模式的作用:從程式的結構上實作松耦合,進而可以擴大整體的類結構,用來解決更大的問題。

2. 擴充卡模式(Adapter)

将一個類的接口轉換成客戶希望的另外一個接口。Adapter模式使得原本由于接口不相容而不能一起工作的那些類可以在一起工作。

設計模式GOF23之第二回

常見的的使用,位元組流轉字元流就是使用擴充卡模式。

java.io.InputStreamReader(InputStream)

java.io.OutputStreamWriter(OutputStream)

3. 代理模式(Proxy)

通過代理,控制對對象的通路! 使對象專注于核心邏輯的處理。

可以詳細控制通路某個(某類)對象的方法,在調用這個方法前做前置處理,調用這個方法後做後置處理。(即:AOP的微觀實作!)

AOP(Aspect Oriented Programming面向切面程式設計)的核心實作機制!實作了橫向,跨類的代碼共享。

應用場景:

  • 安全代理:屏蔽對真實角色的直接通路。
  • 遠端代理:通過代理類處理遠端方法調用(RMI)
  • 延遲加載:先加載輕量級的代理對象,真正需要再加載真實對象。

分類:

  • 靜态代理(靜态定義代理類)
  • 動态代理(動态生成代理類)
  • JDK自帶的動态代理
  • javaassist位元組碼操作庫實作
  • CGLIB
  • ASM(底層使用指令,可維護性較差)

靜态代理

設計模式GOF23之第二回

動态代理

  1. JDK自帶的動态代理

    java.lang.reflect.Proxy

    作用:動态生成代理類和對象

  2. java.lang.reflect.InvocationHandler(處理器接口)

    可以通過invoke方法實作對真實角色的代理通路

    每次通過Proxy生成代理類對象時都要指定對應的處理器對象

設計模式GOF23之第二回

被代理的對象會通過handler成員變量,在每一個方法内部調用invoke(),是以被代理對象所有方法的調用都會進入invoke()方法體内處理。

開源的AOP架構:AspectJ

4. 橋接模式(Bridge)

層次繼承結構中,如果新增一個類别,則需在各分支下新增很多類,導緻擴充性問題。

違反了單一職責原則。存在多個促使類變化的原因。

設計模式GOF23之第二回

建構正交的概念次元,使類之間互相獨立。

設計模式GOF23之第二回

引入橋接模式後

使用組合來代替繼承關系。

設計模式GOF23之第二回

橋接模式總結:

橋接模式可以取代多層繼承的方案。 多層繼承違背了單一職責原則,複用性較差,類的個數也非常多。橋接模式可以極大的減少子類的個數,進而降低管理和維護的成本。

橋接模式極大的提高了系統可擴充性,在兩個變化次元中任意擴充一個次元,都不需要修改原有的系統,符合開閉原則。

橋接模式實際開發中應用場景

  • JDBC驅動程式
  • AWT中的Peer架構
  • 銀行日志管理:
  • 格式分類:記錄檔、交易日志、異常日志
  • 距離分類:本地記錄日志、異地記錄日志
  • 人力資源系統中的獎金計算子產品:
  • 獎金分類:個人獎金、團體獎金、激勵獎金。
  • 部門分類:人事部門、銷售部門、研發部門。
  • OA系統中的消息處理:
  • 業務類型:普通消息、加急消息、特急消息
  • 發送消息方式:系統内消息、手機短信、郵件

5. 組合模式(Composite)

使用組合模式的場景:

  • 把部分和整體的關系用樹形結構來表示,進而使用戶端可以使用統一的方式處理部分對象和整體對象。

組合模式核心:

  • 抽象構件(Component)角色: 定義了葉子和容器構件的共同點
  • 葉子(Leaf)構件角色:無子節點
  • 容器(Composite)構件角色: 有容器特征,可以包含子節點

組合模式工作流程分析:

  • 組合模式為處理樹形結構提供了完美的解決方案,描述了如何将容器和葉子進行遞歸組合,使得使用者在使用時可以一緻性的對待容器和葉子。
  • 當容器對象的指定方法被調用時,将周遊整個樹形結構,尋找也包含這個方法的成員,并調用執行。其中,使用了遞歸調用的機制對整個結構進行處理。
設計模式GOF23之第二回

6. 裝飾模式(Decorator)

職責:

  • 動态的為一個對象增加新的功能。
  • 裝飾模式是一種用于代替繼承的技術,無須通過繼承增加子類就能擴充對象的新功能。使用對象的關聯關系代替繼承關系,更加靈活,同時避免類型體系的快速膨脹。
設計模式GOF23之第二回
設計模式GOF23之第二回

上圖中SuperCar就是Decorator。它作為父類(抽象類)用于儲存傳進來的對象參數。

總結:

  • 裝飾模式(Decorator)也叫包裝器模式(Wrapper)
  • 裝飾模式降低系統的耦合度,可以動态地增加或删除對象的職責,并使得需要裝飾的具體建構類和具體裝飾類可以獨立變化,以便增加新的具體建構類和具體裝飾類。

優點

  • 擴充對象功能,比繼承靈活,不會導緻類個數急劇增加
  • 可以對一個對象進行多次裝飾,創造出不同行為的組合,得到功能更加強大的對象
  • 具體建構類和具體裝飾類可以獨立變化,使用者可以根據需要自己增加新的具體構件子類和具體裝飾子類。

缺點

  • 産生很多小對象。大量小對象占據記憶體,一定程度上影響性能。
  • 裝飾模式易于出錯,調試排查比較麻煩。

裝飾模式和橋接模式的差別:

兩個模式都是為了解決過多子類對象問題。但他們的誘因不一樣。橋模式是對象自身現有機制​

​沿着多個次元變化​

​​,是既有部分不穩定。裝飾模式是為了​

​增加新的功能​

​。

7. 外觀模式(Facade)

迪米特法則(最少知識原則):

一個軟體實體應當盡可能少的與其他實體發生互相作用。

設計模式GOF23之第二回

外觀模式核心:

為子系統提供統一的入口。封裝子系統的複雜性,便于用戶端調用。未使用外觀模式時

設計模式GOF23之第二回

外觀模式

設計模式GOF23之第二回

RegisterFacade類提供了統一處理的界面,收斂了面向用戶端的界面。

在各類工具類XXUtils中都用到了這個“門面”的思想。

8. 享元模式(FlyWeight,輕量級)

場景:

  • 記憶體屬于稀缺資源,不要随便浪費。如果有很多個完全相同或相似的對象,我們可以通過享元模式,節省記憶體。

核心:

  • 享元模式以共享的方式高效地支援大量細粒度對象的重用。

享元對象能做到共享的關鍵是區分了内部狀态和外部狀态。

  • 内部狀态:可以共享,不會随環境變化而改變
  • 外部狀态:不可以共享,會随環境變化而改變

享元模式的實作

設計模式GOF23之第二回

實作要點:

  • 工廠 + 私有屬性(享元池)
  • 外部狀态用專門的類對象單獨處理
  • 内部狀态使用享元類單獨處理
設計模式GOF23之第二回

享元模式常見于各類資源池,如:String常量池,資料庫連接配接池,線程池等。

  • 極大減少記憶體中對象的數量
  • 相同或相似對象記憶體中隻存一份,極大的節約資源,提高系統性能
  • 外部狀态相對獨立,不影響内部狀态
  • 模式較複雜,使程式邏輯複雜化
  • 為了節省記憶體,共享了内部狀态,分離出外部狀态,而讀取外部狀态使運作時間變長。
  • 用時間換取了空間。