--- title: 'Facade 外觀、門面模式' disqus: kyleAlien --- Facade 外觀、門面模式 === ## Overview of Content :::success * 如果喜歡讀更好看一點的網頁版本,可以到我新做的網站 [**DevTech Ascendancy Hub**](https://devtechascendancy.com/) 本篇文章對應的是 [**Facade 外觀、門面模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_facade/) ::: [TOC] ## Facade 使用場景 > **也稱為`門面模式`,外部與內部的通信必須通過一個統一的對象進行**,簡單來說就是一個封裝功能給使用者使用,而使用者不必知道內部細節 * 讓 User 使用系統時不必親自做細節通信 (也不依賴過多類),而是訪問透過外觀類就可使用,**可當作==一層隔離==** > 其實 [**Adapter 適配器模式**](https://hackmd.io/@AlienHackMd/BJ_NojcvU) 就屬於一種小型的外觀模式,不過他更針對指定介面去小規模適配 * 當維護一個遺留的大型系統時,新的類又必須依賴它就可使用外觀模式,外觀模式做仲介;而外觀通常會透過單例模式來訪問,他們對子系統的實現提供了「防變異」、「低耦合的好處」(`GRASP`) 此時外觀用用來隔離新系統訪問舊系統的規則,新系統不會直接觸碰到舊系統,概念程式如下 ```kotlin= class NewSystem { fun doSomething() { if(!Facade.openGate(this)) { return } ... } } // 外觀包裝舊系統 ------------------------------------------ object Facade { private val oldSystem: OldSystem fun openGate(newSystem: NewSystem): Boolean { oldSystem.foo() } } class OldSystem { fun foo() { ... } } ``` ### Facade 定義 & UML * **Facade 定義**:提供提供一個統一界面隔離使用者與子系統 (sub system) 直接的互交,讓使用者使用起來更方便 * Facade UML 角色介紹 | Facade 角色 | 說明 | | - | - | | Facade | 對外使用的窗口,內部持有一個 SubSystem 對象,所有的實做交由 SubSystem 處理 | | SubSystem | 子系統可以有 1 ~ 多個,每個子系統都是單獨的類 | > ![](https://i.imgur.com/VozQemn.png) ### Facade 設計 - 優缺點 * Facade 設計**優點** : 1. 減少子類的依賴,所有細節在外觀類實作,與子類無關 > 解開強耦合:避免外界訪問直接侵入到子系統中 2. 對用戶隱藏細節實現,減少用戶對子系統的依賴以及使用,即使子類產生變化,只需修改外觀類即可 > 符合了高內據的特性 3. 加強了安全性,如果外觀類並無實現功能時,使用者也無法調度子系統 * Facade 設計**缺點** : **不符合開閉原則**,因為需求一做更改勢必會修改此 (`Exterior`) 類別 ### Facade 設計 - 注意事項 * 一個子系統可以有多個門面: 假設一個子系統有許多功能,那相對的門面就會有多個方法,當方法多到一個程度就會難以管理;這時可以 **++依照功能++ 拆分多個門面** * 門面系統 **可以限制使用者的使用** ```kotlin= class Facade { private val subSys = SubSystem() fun working() { // classA 是不限制 subSys.classA.work() } fun workingWithLimit() { // classB 則有限制 subSys.classB.work() } } ``` * **==Facde 門面不應該也不能有具體的業務邏輯==,它的則認識提供一個訪問子系統的路徑而已**,否則它會產生令一個大問題:子系統只能透過門面訪問(這是設計上的嚴重錯誤!) ```kotlin= class Facde { private val subSysA = WorkSystem() private val subSysB = DownloadSystem() // 該函數在門面模式上建構了邏輯!(錯誤) fun workingWithOrder() { if(subSysB.download()) { subSysA.work() } } } ``` 正確解決方式應該是透過 **建立一個封裝類**,並讓門面持有該封裝類讓門面去使用 ```kotlin= 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 標準 1. **`SubSystem` 類**:以下使用 2 個子系統 `Eat`、`Work`,兩個子系統個別提供不同面向的功能 ```kotlin= 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" } } ``` 2. **`Facade` 類**:內部依賴(持有)2 個子系統的實做,並透過操控兩個子系統來達到符合使用者個需求 ```kotlin= 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 類範例: ```kotlin= fun main() { EngineerDay("Alien").run { morning() noon() night() } } ``` > ![](https://i.imgur.com/yuWaiq4.png) ## 更多的物件導向設計 物件導向的設計基礎如下,如果是初學者或是不熟悉的各位,建議可以從這些基礎開始認識,打好基底才能走個更穩(在學習的時候也需要不斷回頭看)! :::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 設計模式` `基礎進階`