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 個子系統 Eat
、Work
,兩個子系統個別提供不同面向的功能
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()
}
}
更多的物件導向設計
物件導向的設計基礎如下,如果是初學者或是不熟悉的各位,建議可以從這些基礎開始認識,打好基底才能走個更穩(在學習的時候也需要不斷回頭看)!
創建模式:Creation Patterns
● 創建模式 PK
● 創建模式 - Creation Patterns
:
創建模式用於「物件的創建」,它關注於如何更靈活、更有效地創建物件。這些模式可以隱藏創建物件的細節,並提供創建物件的機制,例如單例模式、工廠模式… 等等,詳細解說請點擊以下連結
● Singleton 單例模式 | 解說實現 | Android Framework Context Service
● Abstract Factory 設計模式 | 實現解說 | Android MediaPlayer
● Factory 工廠方法模式 | 解說實現 | Java 集合設計
● Builder 建構者模式 | 實現與解說 | Android Framwrok Dialog 視窗
● Clone 原型模式 | 解說實現 | Android Framework Intent
行為模式:Behavioral Patterns
● 行為模式 PK
● 行為模式 - Behavioral Patterns
:
行為模式關注物件之間的「通信」和「職責分配」。它們描述了一系列物件如何協作,以完成特定任務。這些模式專注於改進物件之間的通信,從而提高系統的靈活性。例如,策略模式、觀察者模式… 等等,詳細解說請點擊以下連結
● Stragety 策略模式 | 解說實現 | Android Framework 動畫
● Interpreter 解譯器模式 | 解說實現 | Android Framework PackageManagerService
● Chain 責任鏈模式 | 解說實現 | Android Framework View 事件傳遞
● Specification 規格模式 | 解說實現 | Query 語句實做
● Command 命令、Servant 雇工模式 | 實現與解說 | 物件導向設計
● Memo 備忘錄模式 | 實現與解說 | Android Framwrok Activity 保存
● Visitor 設計模式 | 實現與解說 | 物件導向設計
● Template 設計模式 | 實現與解說 | 物件導向設計
● Mediator 模式設計 | 實現與解說 | 物件導向設計
● Composite 組合模式 | 實現與解說 | 物件導向設計
● Observer 觀察者模式 | JDK Observer | Android Framework Listview
結構模式:Structural Patterns
● 結構模式 PK
● 結構模式 - Structural Patterns
:
結構模式專注於「物件之間的組成」,以形成更大的結構。這些模式可以幫助你確保當系統進行擴展或修改時,不會破壞其整體結構。例如,外觀模式、代理模式… 等等,詳細解說請點擊以下連結
● Decorate 裝飾模式 | 解說實現 | 物件導向設計
● Iterator 迭代設計 | 解說實現 | 物件導向設計