--- title: 'PK - 結構類模式' disqus: kyleAlien --- PK - 結構類模式 === ## Overview of Content 結構類模式有 適配器、橋樑、組合、裝飾、門面、享元、代理模式,這些模式都是透過 **類的「組合」來達到「更大的結構」**,去適應更高層的需求 :::success * 如果喜歡讀更好看一點的網頁版本,可以到我新做的網站 [**DevTech Ascendancy Hub**](https://devtechascendancy.com/) 本篇文章對應的是 [**結構模式 – 3 個 PK | Proxy vs Decorate vs Adapter | 最佳實踐**](https://devtechascendancy.com/pk-design-patterns-proxy-decorate-adapter/) ::: [TOC] ## Proxy、Decorate **裝飾模式可以說是代理模式中的一個特別應用**!兩者最大的不同點在於 **意圖** - **代理模式**:重點是 **代理時機的控制** > 代理者具有絕對的控制權 - **裝飾模式**:重點在於 **加強、減弱原本類的功能** > 原本的類絕對會被執行(代理方無權干預),代理方只能再次增強、減弱原本類的功能 ### Proxy 之控制權 * 我們來實現網路 VPN 的代理,VPN 有辦法控制你是否可以訪問這個區域的網路 > ![](https://hackmd.io/_uploads/S11l1eFHn.png) 1. **界面**: 使用者使用代理重點是關注於界面的合約 ```kotlin= interface IInternet { fun surf(url: String) } ``` 2. **實做功能類**: 這個類是實際功能的實做者 ```kotlin= class InternetImpl: IInternet { override fun surf(url: String) { println("surf on internet, to: $url") } } ``` 3. **代理類**: 該類控制了我們是否真的能訪問到實做類(**它有權力控制**),這也是 **意圖的差別重點** ```kotlin= class VPNProxy: IInternet { private var internet = InternetImpl() override fun surf(url: String) { if (url.startsWith("http://")) { throw Exception("Unsafe access.") } internet.surf(url) } } ``` ### Decorate 之增強、減弱 :::info 裝飾模式如果 省略抽象角色 後,幾本上他們的 UML 類圖可以說是一樣的(所以以下範例把裝飾模式的抽象抽離) ::: * 同樣網路的案例,我們把網路信號做不同的調整,來達到增強、減弱網路的功能 > ![](https://hackmd.io/_uploads/B1PklgKHn.png) 1. **界面**、**實做功能類**:同樣的界面,同樣的實做功能 界面類如下,我們宣告一個簡單的 IInternet 界面,用來接收 URL 做遊覽的動作 ```kotlin= interface IInternet { fun surf(url: String) } ``` 實做功能類,簡單的 print 出 url 就行… 重點是該類屬於 Decorate 的核心(原先)類 ```kotlin= class InternetImpl: IInternet { override fun surf(url: String) { println("surf on internet, to: $url") } } ``` 2. **裝飾類**: 從這個類的意圖,就可以了解到它與代理類的不同;**裝飾類不會去控制是否可以訪問,它只做一個加強(或減弱)的行為** ```kotlin= class Signal5G: IInternet { private var internet = InternetImpl() override fun surf(url: String) { println("5G use faster line.") internet.surf(url) } } ``` ### Proxy vs. Decorate 最佳實踐 * **代理模式**:保證原本類的 **原汁原味的功能**,重點在 **控制外部是否可以訪問** 這個 原汁原味的類~ :::success * 代理模式到了極致就是 **AOP**,透過動態代理、反射來達到業務需求 ::: * **裝飾模式**:原本的類功能仍然會有,但是可能被加強,也可能被縮減,但就是 **不會做是否訪問原類的判斷**(不過率參數...等等) :::info * Java 的 IO 包內就相當多裝飾模式 ::: ## Decorate、Adapter 兩者個相同之處在於,都是 **透過包裝 某個類來達成委託**;但最大的不同點在於 **包裝的對象** * 裝飾模式(Decorate):包裝相同 **有關連的類** * 適配器模式(Adapter):包裝完全沒關係的類,最終達成一個偽裝的類 ### Decorate 之關係包裝 :::success 接下來我們實現一個包裝 Linux Core 的系統概念,透過 Linux 每個不同的組件,對 Linux Core 包裝,並 進行加強 > ![](https://hackmd.io/_uploads/H1yB0Ncrn.png) ::: 1. **包裝界面**:不管是 Decorate 還是 Adapter,他們的核心都是一個界面,指使至中都是針對這個界面的包裝 :::info * 其子類是 **`is-a` 的關係**,也就是 **子類跟這個界面有一定關係** ::: ```kotlin= interface LinuxCore { fun deviceSystem() } ``` 2. **待裝飾類別**:有著基礎的核心功能(以可以說是簡陋的基礎功能) ```kotlin= class GnuCore : LinuxCore { override fun deviceSystem() { println("Use shell to access linux core") } } ``` 3. **裝飾抽象類**:主要是它接收一個抽象核心界面作為成員,再操作其成員來達到加強(或削弱)的功能 ```kotlin= abstract class Decorate(private val base: LinuxCore) : LinuxCore { override fun deviceSystem() { base.deviceSystem() } } ``` 4. **裝飾類**:裝飾的實做類,它為相關類做處理 ```kotlin= class GUI(base: LinuxCore): Decorate(base) { override fun deviceSystem() { super.deviceSystem() println("Use GUI to open window") } } class Application(base: LinuxCore): Decorate(base) { override fun deviceSystem() { super.deviceSystem() println("Use Application control") } } ``` * 使用裝飾關係類來包裝的成果 ```kotlin= fun main() { val root = GnuCore() Application(GUI(root)).deviceSystem() } ``` > ![](https://hackmd.io/_uploads/SkTObN9rh.png) ### Adapter 之偽裝 :::success 我們知道 Window 系統與 Linux 系統的本質就是不同,但我們可以透過 Window 虛擬機(Adapter)來建立一個 Linux 系統 > ![](https://hackmd.io/_uploads/Bk3xJB5Bh.png) ::: 1. **核心界面、實做類**:它 LinuxCore 的界面、實做,也就是核心界面跟實做(可以說是純正血脈~ 將會被某個類偽裝) ```kotlin= // 抽象 interface LinuxCore { fun deviceSystem() } // 實做類 class LinuxImpl : LinuxCore { override fun deviceSystem() { println("Linux core.") } } ``` 2. **假界面**:它與核心界面的功能一模一樣,不過其實是外部將會偽裝的界面(就是要假扮所以方法才一樣阿) :::warning * 兩個界面都有 `deviceSystem` 方法,但其實 **兩者是沒有關係的**! ::: ```kotlin= interface IWindowVM { fun deviceSystem() } ``` 3. **假類**:虛擬機類,它內部擁有一個 真實的 `LinuxCore` 界面實做,透過它來模擬訪問 LinuxCore ```kotlin= class WindowVMAdapter : IWindowVM { private val linux = LinuxImpl() override fun deviceSystem() { println("Window VM.") linux.deviceSystem() } } ``` * Window 使用 WindowVM 來運行 Linux ```kotlin= fun main() { WindowVMAdapter().deviceSystem() } ``` > ![](https://hackmd.io/_uploads/HJ1RcVqrn.png) ### Decorate vs. Adapter 最佳實踐 * **意圖不同** * **Decorate**:意圖在「加強(減弱)」原生對象的核心功能 * **Adapter**:意圖在於「轉換」,**與原來類可以沒有任何關係** * **施予目標不同** * **Decorate**:裝飾對象必須是自己的同宗,也就是有 **相同的父類、界面** * **Adapter**:適配對象則是兩個完全不同的對象,不必有繼承、實做關係 * **場景不同** * **Decorate**:多用在功能增強上 * **Adapter**:**比較常用於補救、緊急手段** * **擴展性不同** * **Decorate**:簡易、方便拓展(或移除) * **Adapter**:由於兩者之間是靠邏輯手動產生關係的,所以拆開時也需要判別邏輯 ## 更多的物件導向設計 物件導向的設計基礎如下,如果是初學者或是不熟悉的各位,建議可以從這些基礎開始認識,打好基底才能走個更穩(在學習的時候也需要不斷回頭看)! :::info * [**設計建模 2 大概念- UML 分類、使用**](https://devtechascendancy.com/introduction-to-uml-and-diagrams/) * [**物件導向設計原則 – 6 大原則(一)**](https://devtechascendancy.com/object-oriented-design-principles_1/) * [**物件導向設計原則 – 6 大原則(二)**](https://devtechascendancy.com/object-oriented-design-principles_2/) ::: ### 創建模式 - Creation Patterns * [**創建模式 PK**](https://devtechascendancy.com/pk-design-patterns-factory-builder-best/) * **創建模式 - `Creation Patterns`**: 創建模式用於「**物件的創建**」,它關注於如何更靈活、更有效地創建對象。這些模式可以隱藏創建對象的細節,並提供創建對象的機制,例如單例模式、工廠模式… 等等,詳細解說請點擊以下連結 :::success * [**Singleton 單例模式 | 解說實現 | Android Framework Context Service**](https://devtechascendancy.com/object-oriented_design_singleton/) * [**Abstract Factory 設計模式 | 實現解說 | Android MediaPlayer**](https://devtechascendancy.com/object-oriented_design_abstract-factory/) * [**Factory 工廠方法模式 | 解說實現 | Java 集合設計**](https://devtechascendancy.com/object-oriented_design_factory_framework/) * [**Builder 建構者模式 | 實現與解說 | Android Framwrok Dialog 視窗**](https://devtechascendancy.com/object-oriented_design_builder_dialog/) * [**Clone 原型模式 | 解說實現 | Android Framework Intent**](https://devtechascendancy.com/object-oriented_design_clone_framework/) * [**Object Pool 設計模式 | 實現與解說 | 利用 JVM**](https://devtechascendancy.com/object-oriented_design_object-pool/) * [**Flyweight 享元模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_flyweight/) ::: ### 行為模式 - Behavioral Patterns * [**行為模式 PK**](https://devtechascendancy.com/pk-design-patterns-cmd-strat-state-obs-chain/) * **行為模式 - `Behavioral Patterns`**: 行為模式關注物件之間的「**通信**」和「**職責分配**」。它們描述了一系列對象如何協作,以完成特定任務。這些模式專注於改進物件之間的通信,從而提高系統的靈活性。例如,策略模式、觀察者模式… 等等,詳細解說請點擊以下連結 :::warning * [**Stragety 策略模式 | 解說實現 | Android Framework 動畫**](https://devtechascendancy.com/object-oriented_design_stragety_framework/) * [**Interpreter 解譯器模式 | 解說實現 | Android Framework PackageManagerService**](https://devtechascendancy.com/object-oriented_design_interpreter_framework/) * [**Chain 責任鏈模式 | 解說實現 | Android Framework View 事件傳遞**](https://devtechascendancy.com/object-oriented_design_chain_framework/) * [**State 狀態模式 | 實現解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_state/) * [**Specification 規格模式 | 解說實現 | Query 語句實做**](https://devtechascendancy.com/object-oriented_design_specification-query/) * [**Command 命令、Servant 雇工模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_command_servant/) * [**Memo 備忘錄模式 | 實現與解說 | Android Framwrok Activity 保存**](https://devtechascendancy.com/object-oriented_design_memo_framework/) * [**Visitor 設計模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_visitor_dispatch/) * [**Template 設計模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_template/) * [**Mediator 模式設計 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_programming_mediator/) * [**Composite 組合模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_programming_composite/) ::: ### 結構模式 - Structural Patterns * [**結構模式 PK**](https://devtechascendancy.com/pk-design-patterns-proxy-decorate-adapter/) * **結構模式 - `Structural Patterns`**: 結構模式專注於「物件之間的組成」,以形成更大的結構。這些模式可以幫助你確保當系統進行擴展或修改時,不會破壞其整體結構。例如,外觀模式、代理模式… 等等,詳細解說請點擊以下連結 :::danger * [**Bridge 橋接模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_bridge/) * [**Decorate 裝飾模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_decorate/) * [**Proxy 代理模式 | 解說實現 | 分析動態代理**](https://devtechascendancy.com/object-oriented_design_proxy_dynamic-proxy/) * [**Iterator 迭代設計 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_iterator/) * [**Facade 外觀、門面模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_facade/) * [**Adapter 設計模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_adapter/) ::: ## Appendix & FAQ :::info ::: ###### tags: `Java 設計模式`