第 5 / 11 部 待錄

結構型模式I-轉接橋接與門面

《Design Patterns 設計模式(GoF)》Podcast 準備稿:結構型模式 I — Adapter、Bridge 與 Facade

書名: 設計模式 Design Patterns(Elements of Reusable Object-Oriented Software) 作者: Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides(Gang of Four) 系列: 啃一本大書(恩普拉氏) 公開標題建議: 啃一本大書|Design Patterns.接上去、橋過去、包起來:Adapter/Bridge/Facade (5/11) 涵蓋範圍: 結構型模式總覽 + Adapter、Bridge、Facade(深講)

背景速覽

進入 Structural Patterns(結構型模式),這類七個模式關注的是「如何把 class 和物件組合成更大的結構」。如果說創建型管「物件怎麼生」、行為型管「物件怎麼互動」,那結構型就管「物件怎麼拼裝在一起」。

這集挑三個處理「介面與依賴」的模式:Adapter(轉接器)——讓不相容的介面合作;Bridge(橋接)——讓抽象和實作各自獨立演化;Facade(門面)——給一個複雜子系統一個簡單入口。三個都在「整理介面」,但切入點截然不同,對照著講最有收穫。

一句話重點

Adapter 是「事後」把一個既有類別的介面轉換成你要的樣子;Bridge 是「設計初期」就把抽象與實作拆成兩條可獨立演化的軸;Facade 則是替一坨複雜子系統開一扇簡單的門,但不擋你直接進去。

值得討論的重點

1. 結構型模式的兩種玩法:繼承 vs 組合

開場給地圖:結構型模式分兩路——class 版用繼承來組合介面或實作(如 class Adapter 用多重繼承);object 版用物件組合來拼出新功能。後者的彈性在於可以run-time 動態改變組合,這是靜態繼承做不到的。七個模式裡,object 版佔多數——又一次呼應「組合勝過繼承」。

2. Adapter:讓不相容的介面握手

Intent:把一個類別的介面轉換成 client 期望的另一個介面。別名 Wrapper

動機:繪圖編輯器有抽象 Shape,你想重用一個現成的 TextView,但它的介面跟 Shape 不相容、又不能改它的原始碼。解法是寫一個 TextShape 當 adapter——對外長得像 Shape,內部把請求翻譯成 TextView 的呼叫。

兩種做法要對照講:

  • Class Adapter(多重繼承):同時繼承 Shape 的介面和 TextView 的實作。優點是能覆寫 Adaptee 行為、少一層間接;缺點是綁死具體 Adaptee 類別、無法適配其子類別。
  • Object Adapter(組合)TextShape 內含一個 TextView 實例,用委派實作。優點是一個 adapter 能服務 Adaptee 及其所有子類別;缺點是較難覆寫 Adaptee 行為。

現代多半用 object adapter(組合版),因為很多語言沒有多重繼承,而且組合更靈活。

要點睛一句:Adapter 不只是改名字。 它還能補上被適配類別缺的功能(TextShape 可以自己實作 Shape 要的拖曳操作,即使 TextView 沒有)。

3. Bridge:把「抽象」和「實作」拆成兩條軸

Intent:把抽象與其實作分離,使兩者可以獨立變化。別名 Handle/Body

動機(呼應 EP2 的 Lexi 視窗問題):一個 Window 抽象要支援 X Window 和 PM 兩種系統。如果用繼承——XWindowPMWindow,再加一種視窗類型 IconWindow,就要 XIconWindowPMIconWindow……類別數量乘法爆炸

Bridge 的解法:把它拆成兩個獨立的繼承階層——

  • 抽象層WindowIconWindowDialogWindow(面向應用開發者的邏輯需求)。
  • 實作層WindowImpXWindowImpPMWindowImp(面向平台能力)。

Window 持有一個 WindowImp,把操作委託過去。這個委託關係就是「橋」。於是兩條軸各自獨立加子類別,從「m × n 個類別」變成「m + n 個類別」。

核心句子:以組合取代多重繼承來處理正交的變化維度。 當你發現「我這東西有兩個獨立會變的方向」(抽象方向 ×實作方向),就是 Bridge 登場的訊號。

4. Facade:給複雜子系統一扇簡單的門

Intent:為子系統中的一組介面提供一個統一的高層介面,讓子系統更好用。

動機:一個編譯器子系統有 ScannerParserProgramNodeBuilderBytecodeStream……一堆類別。但大多數 client 只想「編譯這段程式碼」,不關心解析細節。解法是給一個 Compiler 類別當 facade——提供「編譯」這個單一簡化入口,把底層黏起來。

關鍵分寸(這點 GoF 講得很漂亮):Facade 不是要擋住你用子系統,而是給一條捷徑。 大多數人走 facade 的方便門;少數需要精細控制的人,仍然可以直接用底層類別。便利與控制,自己選。

好處:減少 client 面對的物件數量、促進弱耦合(子系統能自由變動而不影響 client,還能減少重新編譯時間)。

注意事項

⚠️ Adapter 和 Bridge 結構幾乎一樣(object adapter 跟 Bridge 幾乎一模一樣),但意圖完全相反——這是這集最容易翻車的地方。 記法:Adapter 是「事後補救」——兩個東西已經存在、介面對不上,你補一個轉接頭;Bridge 是「事前規劃」——你在設計初期就預見「抽象和實作會各自變」,主動把它們拆開。一個是修,一個是防。務必把這句講到聽眾能複述。

⚠️ Facade 和「上帝物件」只有一線之隔。 Facade 是把複雜「藏在後面」的薄薄一層,它本身不該塞業務邏輯。一旦你的 facade 開始什麼都做、變成幾千行的巨獸,它就從「簡化入口」墮落成「上帝物件」了。Facade 該瘦,不該胖。

專家補充

💡 Adapter 是你最常『不知不覺就用上』的模式。 任何時候你包一個第三方函式庫、把它的 API 翻譯成你系統的介面——那就是 Adapter。它的價值不只是相容,更是把外部依賴隔離在一層之後:哪天那個函式庫要換掉,你只改 adapter,不動整個系統。這跟《Clean Architecture》(Uncle Bob) 的「邊界」「把框架推到外圈」是同一個智慧。

💡 Bridge 的「正交變化軸」直覺,比模式本身更值錢。 很多設計災難的根源,是把兩個本該獨立的變化方向,硬塞進同一條繼承鏈,於是每加一個維度就指數爆炸。學會問「我這裡是不是有兩個獨立會變的方向?」——光是這個提問,就能讓你避開大量糟糕設計。Bridge 只是這個提問的標準答案之一。

💡 Facade 在「分層架構」與「微服務」時代被放大了。 你的 service layer 對 controller 來說是 facade;API gateway 對前端來說是 facade;BFF(Backend for Frontend)整個就是 facade 思想。Facade 不只是個小模式,它是「分層、隔離複雜度」這個架構原則的最小單位。

討論問題

🎙️ 開場鉤子:「接上去、橋過去、包起來——今天三個模式,做的都是『整理介面』這件事,但時機完全不同。一個在事後修、一個在事前防、一個在外面包。聽完你就再也不會把 Adapter 和 Bridge 搞混了。」

🎙️ 自問自答:「Adapter 和 Bridge 結構這麼像,到底差在哪?」——時機。Adapter 是『兩個東西已經存在、介面對不上,我補個轉接頭』;Bridge 是『我預見抽象和實作會各自變,一開始就拆兩條軸』。修 vs 防。

🎙️ 帶走的一題:「找找你系統裡包第三方函式庫的地方——如果你直接到處呼叫它的 API,沒有包一層,那哪天要換掉它,你會很痛。試著想想:這裡是不是該補一個 Adapter,把外部依賴關在一層之後?」

更大範圍關聯

  • 與 Clean Architecture 的邊界思想:Adapter/Facade 都是「隔離外部依賴、守住邊界」的手法,與 Uncle Bob《Clean Architecture》的同心圓、把框架與細節推到外圈完全呼應(見 [軟體工程領域切分藍圖])。
  • Facade 與分層/微服務:service layer、API gateway、BFF 都是 Facade 在架構尺度上的放大。
  • Adapter 的當代日常:任何「wrapper / shim / 防腐層(Anti-Corruption Layer,DDD 概念)」本質都是 Adapter。
  • 下一集預告:結構型還有四個——Composite、Decorator、Flyweight、Proxy。EP6 深講「遞迴組合雙人組」Composite + Decorator。

錄製建議

  • 建議時長:約 22-24 分鐘。配比:結構型總覽約 3 分、Adapter 約 6 分、Bridge 約 7 分、Facade 約 5 分、Adapter vs Bridge 對照釐清約 3 分。
  • 討論策略:三個模式都先講「痛點」再講「解法」。最關鍵的教學點是 Adapter vs Bridge 的時機差異,這要當本集的高潮,用「修 vs 防」一句話釘死。Facade 段帶到分層架構,給聽眾「小模式其實對應大原則」的縱深。
  • 提醒聽眾:這三個模式在真實程式碼裡出現頻率很高,尤其 Adapter——他們很可能已經寫過卻不知道那叫 Adapter。