---
# System prepended metadata

title: PK - 結構類模式
tags: [Java 設計模式]

---

---
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 設計模式`
