設計模式不是理論,而是經驗語言

·8 min

此為《Learning JavaScript Design Patterns, 2nd Edition》學習筆記,對應第 1 章(Introduction to Design Patterns)

從建築到程式

設計模式這個概念,其實不是從程式設計領域冒出來的。最早是建築師在思考:為什麼有些房子、街道、社區特別好用、住起來也格外舒服?在反覆觀察後,他發現這些設計往往有共通的做法。於是他開始把這些做法整理下來,並幫它們取了名字,讓它們成為一種「設計經驗的語言」。

多年後,軟體工程師也遇到相同的困擾:為什麼有些程式架構清晰易懂,維護起來很順手,而有些卻總是陷入混亂?他們借來這個概念,把程式設計中一再出現的好做法整理並命名,從此之後,開發者在討論程式設計就多了一套共通的語言。

我最初的理解盲點

回想我第一次讀這本書的時候,我總覺得設計模式是一種「理論框架」,以為重點就是要把理論硬套到實際問題裡。因為這樣的想法,我一直停留在只認得名詞的階段,卻沒有真正理解背後的脈絡,這是我後來才發現的誤解。

下面這張流程圖,反映了我當時的誤解。我以為設計模式就是把理論直接轉換成程式碼,中間不需要經驗的累積或設計上的思考。

flowchart TB
  X["理論 / 規範"] --> Y["設計模式"]
  Y --> Z["程式碼怎麼寫"]

解法,又不是解法?

即使知道自己以前的誤解,再次閱讀的時候,我還是遇到了一些新的困惑。書裡一方面說:

Patterns provide generalized solutions, documented in a fashion that doesn’t require them to be tied to a specific problem.

另一方面又說:

Patterns are not exact solutions.

當下我真的看不懂,甚至覺得作者前後矛盾。直到後來透過 AI 舉的 Observer 模式例子,我才慢慢理解,原來這兩句話其實是在講不同的面向。

設計模式不是拿來就能直接解決問題的程式碼,而是一種幫助思考的設計方向。就像一張地圖,它可以告訴我大致的路線,但真正要怎麼走,還是得依照地形和情境自己判斷。

模式是如何誕生的?

想通這些之後,我開始對「設計模式是怎麼形成的」這件事比較有概念。

大概就是:先有一個反覆出現的問題,不同的人會想出各種解法。這些解法雖然做法或樣子不同,但仔細觀察會發現它們有一些共通的特徵。等這些經驗被驗證、慢慢累積下來,最後就有人幫它取了一個名字,成為「設計模式」。至於程式碼要怎麼寫,則會依照語言或框架的不同,有很多種做法。

flowchart TB
  A["問題"] -- "嘗試不同方式" --> B["解法 A / B / C"]

  B -- "歸納+驗證+經驗累積" --> E["共通的解法"]

  E -- "經過命名與紀錄" --> F["設計模式"]
  E -- "依語言 / 框架 / 情境而異" --> G["程式碼怎麼寫"]

用 Observer 模式打通思路

這個例子不是我自己想出來的,而是當我卡在「到底設計模式是解決方案,還是不是解決方案?」這個矛盾點時,AI 給我的例子。透過這個例子,我才更清楚看到設計模式是怎麼從現實常遇到的問題一路被歸納、命名,再到不同情境下的實作方式。

下面這張流程圖,是 Observer 模式形成過程的視覺化呈現:

flowchart TB
    A["問題:狀態改變時,其他物件也要同步更新(例如:事件通知)"] -- 嘗試不同方式 --> B["解法 A:主動呼叫多個函式"] & C["解法 B:輪詢檢查狀態"] & D["解法 C:傳 callback 函式"]
    B -- 歸納共通點 --> E["共通的解法:一對多通知機制"]
    C -- 歸納共通點 --> E
    D -- 歸納共通點 --> E
    E -- 經過命名與記錄 --> G["設計模式:<br>Observer(觀察者模式)"]
    E -- 依情境而異的實作方式 --> F["程式碼怎麼寫:<br>JS addEventListener / Node.js EventEmitter / PubSub library"]

一個常見問題

當一個物件的狀態改變時,系統裡其他相關物件也要跟著更新。

例子:

  • 按下按鈕 → UI 要更新
  • 股票價格變動 → 多個投資人要收到通知

各種解決嘗試

  • 有人直接在程式裡寫死「按鈕呼叫三個不同的函式」
  • 有人用輪詢(polling)的方式,不斷檢查狀態
  • 有人用 callback,把要做的事事先交給狀態持有者,等狀態改變時再呼叫

雖然方法不同,但核心其實都是在解決「一對多的狀態同步需求」。

歸納共通的藍圖

於是有人把這些經驗整理出來,歸納成一個通用的方法: 有一個 Subject(被觀察者),負責維護狀態,並記錄有哪些 Observers(觀察者)。 當狀態改變時,Subject 通知所有 Observers 去做對應的更新。

👉 這樣,Observer 模式就誕生了。

不同情境的實作

  • 在 JavaScript 裡,你可能用 addEventListener(DOM 事件)
  • 在 React 裡,你可能用 state → props 傳遞,或搭配 Context/Redux
  • 在資料庫同步裡,你可能用 Pub/Sub(發佈/訂閱)

它們都是 Observer 模式的應用,但實際寫法和細節會依情境而異。

藍圖,而非答案

Observer 模式這個例子,幫我解開了當時的困惑:

  • 設計模式能提供共通的藍圖
  • 但它不會告訴你唯一的程式碼答案
  • 真正的寫法,要看你用什麼語言、框架,還有需求是什麼

總結

讀完第一章後,我才搞懂,自己在技術溝通上之所以常常卡住,其實是因為一直誤解了設計模式。它不是抽象的理論,而是累積下來的經驗語言。這也剛好解釋了,為什麼我和資深同事討論時常跟不上,和新手交流時又給不出關鍵字。也因為這樣,我才決定展開《從零開始學 JavaScript 設計模式》這個學習計劃。

感謝你讀到這裡!如果我的分享讓你有所共鳴或啟發,歡迎請我喝杯珍奶 🧋,給我一點繼續分享的能量: https://anna.bobaboba.me