Facade 外觀、門面模式 | 解說實現 | 物件導向設計

Facade 外觀、門面模式 | 解說實現 | 物件導向設計

Overview of Content

在這篇文章中,我們將探討外觀模式(Facade Pattern,又稱為門面模式,在物件導向設計中的實現與解說。

首先,我們會提供整體內容的概述,深入了解外觀模式的核心概念。接著,我們將探討外觀模式的使用場景,並解釋其定義和UML結構。在設計方面,我們會詳細討論外觀模式的優缺點,以及在應用時需要注意的事項。

在實際實現部分,我們探討外觀模式的標準實現方式,以示範如何在設計中運用此模式,以提升系統的易用性和簡化客戶端與子系統的交互。透過本文,讀者將全面了解外觀模式的實際應用及其在物件導向設計中的價值。


Facade 使用場景

也稱為門面模式,外部與內部的通信必須通過一個統一的對象進行,簡單來說就是一個封裝功能給使用者使用,而使用者不必知道內部細節

● 讓 User 使用系統時不必親自做細節通信 (也不依賴過多類),而是訪問透過外觀類就可使用,可當作一層隔離

● 當維護一個遺留的大型系統時,新的類又必須依賴它就可使用外觀模式,外觀模式做仲介

Facade 定義 & Facade UML

Facade 定義:提供提供一個統一界面隔離使用者與子系統 (sub system) 直接的互交,讓使用者使用起來更方便

● Facade UML 角色介紹

Facade 角色說明
Facade對外使用的窗口,內部持有一個 SubSystem 對象,所有的實做交由 SubSystem 處理
SubSystem子系統可以有 1 ~ 多個,每個子系統都是單獨的類

Facade 設計:優缺點

● Facade 設計優點 :

A. 減少子類的依賴,所有細節在外觀類實作,與子類無關

解開強耦合:避免外界訪問直接侵入到子系統中

B. 對用戶隱藏細節實現,減少用戶對子系統的依賴以及使用,即使子類產生變化,只需修改外觀類即可

符合了高內據的特性

C. 加強了安全性,如果外觀類並無實現功能時,使用者也無法調度子系統

● Facade 設計缺點 :

不符合開閉原則,因為需求一做更改勢必會修改此 (Exterior) 類別

Facade 設計:注意事項

● 一個子系統可以有多個門面:

假設一個子系統有許多功能,那相對的門面就會有多個方法,當方法多到一個程度就會難以管理;這時可以 依照功能 拆分多個門面

● 門面系統 可以限制使用者的使用


class Facade {

    private val subSys = SubSystem()

    fun working() {
        // classA 是不限制
        subSys.classA.work()
    }

    fun workingWithLimit() {
        // classB 則有限制
        subSys.classB.work()
    }

}

Facde 門面不應該也不能有具體的業務邏輯,它的則認識提供一個訪問子系統的路徑而已,否則它會產生令一個大問題:子系統只能透過門面訪問(這是設計上的嚴重錯誤!)


class Facde {

    private val subSysA = WorkSystem()
    private val subSysB = DownloadSystem()

    // 該函數在門面模式上建構了邏輯!(錯誤)
    fun workingWithOrder() {
        if(subSysB.download()) {
            subSysA.work()
        }
    }
}   

正確解決方式應該是透過 建立一個封裝類,並讓門面持有該封裝類讓門面去使用


class MyRequest {
    private val subSysA = WorkSystem()
    private val subSysB = DownloadSystem()

    fun checkAndWork() {
        if(subSysB.download()) {
            subSysA.work()
        }
    }
}


class Facde {

    private val subSysA = WorkSystem()
    private val subSysB = DownloadSystem()
    private val subSysC = MyRequest()

    // 該函數在門面模式上建構了邏輯!(錯誤)
    fun workingWithOrder() {
        subSysC.checkAndWork()
    }
}   

Facade 實現

Facade 標準實現

A. SubSystem:以下使用 2 個子系統 EatWork,兩個子系統個別提供不同面向的功能


class Eat {    // 子系統 1 
    fun eatBreakfast(): String {
        return " Breakfast"
    }

    fun eatLunch(): String {
        return " Lunch"
    }

    fun eatDinner(): String {
        return " Dinner"
    }
}

class Work {    // 子系統 2 
    fun monWork(): String {
        return " Coding"
    }

    fun afternoonWork(): String {
        return " Rearch"
    }

    fun nightWork(): String {
        return " Write Note"
    }
}

B. Facade:內部依賴(持有)2 個子系統的實做,並透過操控兩個子系統來達到符合使用者個需求


class EngineerDay(name: String) {
    
    // 依賴多個子系統
    private val e: Eat = Eat()
    private val w: Work = Work()
    private val name: String

    init {
        this.name = name
    }

    // 使用子系統達成使用者需求
    fun morning() {
        println(name + e.eatBreakfast())
        println(name + w.monWork())
    }

    fun noon() {
        println(name + e.eatLunch())
        println(name + w.afternoonWork())
    }

    fun night() {
        println(name + e.eatDinner())
        println(name + w.nightWork())
    }
}

● 使用 Facade 類範例:


fun main() {
    EngineerDay("Alien").run {
        morning()

        noon()

        night()
    }
}

更多的物件導向設計

物件導向的設計基礎如下,如果是初學者或是不熟悉的各位,建議可以從這些基礎開始認識,打好基底才能走個更穩(在學習的時候也需要不斷回頭看)!

設計建模 2 大概念- UML 分類、使用

物件導向設計原則 – 6 大原則(一)

物件導向設計原則 – 6 大原則(二)

創建、行為、結構型設計 8 個比較 | 包裝模式 | 最佳實踐

創建模式:Creation Patterns

創建模式 PK

創建模式 - Creation Patterns

結構模式:Structural Patterns

結構模式 PK

結構模式 - Structural Patterns

結構模式專注於「物件之間的組成」,以形成更大的結構。這些模式可以幫助你確保當系統進行擴展或修改時,不會破壞其整體結構。例如,外觀模式、代理模式… 等等,詳細解說請點擊以下連結

Bridge 橋接模式 | 解說實現 | 物件導向設計

Decorate 裝飾模式 | 解說實現 | 物件導向設計

Proxy 代理模式 | 解說實現 | 分析動態代理

Iterator 迭代設計 | 解說實現 | 物件導向設計

Facade 外觀、門面模式 | 解說實現 | 物件導向設計

Adapter 設計模式 | 解說實現 | 物件導向設計

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

發表迴響