我最近在整理以前讀過的書。這篇想寫《設計模式的解析與活用》。

英文原著是《Design Patterns Explained》,Alan Shalloway 和 James Trott 寫的。
我入門設計模式,是靠 Refactoring.Guru 那個網站,還有《Head First 設計模式》。那時候我以為把這些 pattern 看過一遍、知道它們在幹嘛,就等於會用了。工廠、觀察者、單例、策略,名字我都叫得出來。
但真的要動手,還是很模糊。我知道有這個 pattern,卻不知道什麼時候該把它拿出來,也不知道怎麼套到自己手上的問題。知道一份 pattern 清單,跟會用,中間差了一大段。
這一段,是《設計模式的解析與活用》幫我補起來的。它沒有給我一份目錄,而是把思考方式拆開來給我看。整本書帶你從頭設計一個真實的軟體——書裡那個例子,是一套機械板金零件的 CAD/CAM 設計系統。它不是告訴你「這裡用工廠模式」,是讓你看作者遇到這個問題時,腦子怎麼一步步轉的。
背模式和用模式思考,聽起來很像,其實差很遠。一個是記住答案,一個是學會怎麼走到答案。
書裡有一段我印象很深。作者在苦思那個 CAD/CAM 系統的設計,用標準物件導向的做法怎麼想都不對,後來乾脆放棄,起身去走一走。走了大概 30 步,突然就頓悟了。我第一次讀只覺得是個勵志小故事,後來才發現他想講的是:模式不是拿來套的答案,是拿來當思考方向的。它幫你把問題問對。
作者在書裡把「用模式思考」拆成幾步。先找出模式;再分析和應用,這裡又分成依營運需求調整、選合適的模式、找到關鍵點、重新評估;最後才是增加價值。你會發現裡面沒有一步是「把 pattern 背出來」,每一步都在跟問題本身對話。
那要怎麼跟問題對話?書裡最核心的一招,叫共通性/變化性分析。聽起來很學術,其實很白話:把問題裡不會變的部分和會變的部分分開。CAD/CAM 那個例子,共性是「CAD/CAM 系統」,變化是 V1、V2;共性是「部件」,變化是溝槽、孔、方切口、特殊形狀。
一旦把共性和變化切開,設計幾乎就自己浮出來了。不變的定成介面,會變的各自去實作。這時候回頭看,會發現這就是相依倒置,也根本就是 Abstract Factory 在做的事。但你不是先想到 Abstract Factory 才去套,你是先把問題想清楚,然後發現「欸,這個形狀剛好就是某個模式」。
模式是結果,不是起點。
書裡還有一張表,我覺得比板金那個例子更好懂。你要做一個電商,先在美國賣,後來加拿大,後來德國。作者不急著寫程式,先畫一張表:每一列是一件要做的事——算運費、驗地址、算稅、幣別、日期格式;每一欄是一個市場——美國、加拿大、德國。然後一格一格填下去。
填的過程,會變的地方全被逼出來。運費,美國 UPS、加拿大 FedEx、德國本地貨運。稅,美國州稅、加拿大 GST/PST、德國 VAT。日期,美國 mm/dd、德國 dd/mm。
我覺得最有意思的反而是那些空格。德國那欄有一個「最大重量 30 公斤」,美國和加拿大那格是空的。空格不一定代表沒有,比較可能是客戶根本沒提到。作者說,這時候與其問客戶「還有別的嗎」,不如直接問「你們有沒有重量限制」。具體的問題,才問得出真正的答案。
這張表在幹嘛?就是幫你把「哪些東西會變」一次找齊。你得先找齊,才有得談要不要封裝、怎麼封裝。我後來才懂,用模式思考的起點不是模式,是把問題看清楚。
另一個例子我很有共鳴。一個小組要支援很多合作夥伴公司的系統,核心規則差不多,但每家總有一點點不一樣。於是程式碼裡開始長出一堆 if-then-else,再不然就是整段複製貼上、改幾個地方。這兩條路我都走過。if 一多,就變成作者說的「分支蔓延」;複製貼上,就變成到處都要改、到處都會漏。
書裡給的第三條路是 Template Method。先找出這些情況裡共同的流程,把共同的抽出來,把不同的部分抽象化。其實還是同一招:分開不變的和會變的。讀到這裡我才意識到,這本書換各種角度,其實一直在講同一件事——封裝變化。而這件事,你背 pattern 是背不出來的。
背 pattern 更背不出來的是,真實的設計很少只用一個模式。CAD/CAM 那個解,作者最後是把好幾個模式交織在一起:Abstract Factory、Bridge、Facade、Adapter。Bridge 撐起骨架,Abstract Factory 負責生出整組物件,Facade 把舊的 V1 系統包成一個乾淨的入口,Adapter 去轉接 V2 的介面。沒有一個是主角,它們是一起工作的。
作者還講了一件我覺得很妙的事:模式之間會互相給線索。你先認出一個,另一個往往就跟著浮出來。所以真正難的從來不是記得那 23 個模式,是看得出這個問題裡藏了幾個會變的點,該用哪幾個模式一起收。
這套思考方式,放到現在反而更有意思。因為那些有固定寫法、照慣用法走的實作,很多都可以交給 AI 了。你要一段 thread-safe 的單例,AI 直接寫給你;你要把一堆 if 換成策略模式,AI 也能重構。這種東西,AI 記得比我熟。
那我還要背 pattern 嗎?讀完這本書,我的答案變得很清楚:要背的從來不是那些寫法,是背後的判斷。像是這裡有個會變的東西,要不要封裝起來;這段共同流程,要不要抽成 Template;這兩個概念,是不是該用介面隔開。這些判斷 AI 幫不了你,因為它不知道你的系統接下來會往哪裡變。只有你在跟問題對話的時候才知道。
這也是我覺得這本書 Old School,但一點都沒過時的原因。它教的不是 23 個答案,是遇到一個新問題時,怎麼把它拆開、怎麼問對問題、怎麼找到那個會變的點。
背模式,是背別人走過的路。用模式思考,是自己有能力走一條新的。AI 可以幫你把路鋪好,但要往哪走,還是得你自己看得懂地形。