English version:
英文版在 hackmd
本文包涵:
以物件導向 (Object-oriented programming, OOP)設計程式時,常遵循 SOLID 原則:
每個模組 (module)或類別 (class)只做一件事,利於維護與測試
例如:處理登入模組,不該出現結帳功能 (白話:菜刀不兼鍋鏟職)
程式碼應對「擴展」開放,對「修改」封閉
例如:想增加登入驗證,應「另建模組」,而非「直些修改舊模組」
後代需具備祖先的所有特徵
例如:卡車屬於車,但車不一定是卡車 (卡車有輪胎、引擎等一切車子應有的組件,但「車」不只有卡車一種)
若你想開卡車去旅行,它當然能勝任 (旅遊品質是另一回事)
敞篷車、轎車、卡車都能稱作車,所以都能代步 (功能不變)
不應強迫用戶實作不會用到的功能
例如:我只想 掃描
文件,使用 印表機
介面時,就不該強迫我使用 列印
功能
高階模組不依賴低階模組,而應依賴抽象 (Abstraction),低階模組實作抽象
例如:電視遙控器 (低階)壞了,只需要再買一個,不用連電視 (高階)都換掉
因為電視不依賴遙控器,兩者依賴特定訊號協定 (抽象)
SOLID 只是指導原則,設計仍保有高度彈性
有基本概念後,就來看看常見的設計模式吧!
先看統整再細說:
常見設計模式總覽
製表人:我自己
先做出樣品,再靠複製來生產物件 (樣品 = 原型 = 模板)
做過報告就知道,複製貼上比從頭打字快多了
想更新產品,只需修改模板
Ctrl
+ C
→ Ctrl
+ V
當然不會這麼爛XD
原型 (Prototype):套模生產
圖源:又是我
一類別 (class)一實例 (instance),並提供全域存取點
全域存取點共用,即同個資源池大家分
實例化 (instantiation)時,物件才取得資源。所以若只需實例化一次,就不需要不斷獲取資源 (想像不斷開關冷氣 vs 開著冷氣,前者更耗電)
所有人 (或物件)都需從全域存取點獲得服務,則只需管理該存取點,不必為每個終端 (使用者/物件)個別服務
這是個經典案例,若每個用戶訪問時,都需取得資料庫連線、用完再關閉,會很耗資源
反之,先取得一堆連線 (i.e. 連線「池」),使用者訪問時分配一個給他,用完再丟回池中,後者較省資源
電腦只需一個日誌管理員,處理各種系統日誌
各程式可有獨立設定檔,但讀取可用同個管理員
這應該最好理解。不會因為你我都要辦護照,政府就生出兩個外交部。
「政府」即為類別 (class),「外交部實體」便是實例 (instance)
→ 不利單元測試 (unit test)
→ 修改局部程式碼,可能影響其他功能 (牽一髮動全身)
全域存取點即為全域變數
若程式沒特別處理,每個執行緒都會產生實例
→ 可藉雙重檢查鎖定 (Double-Checked Locking Pattern,又稱「鎖暗示 (lock hint)」)解決 --- 非本文重點,故不在此贅述
單例模式 (Singleton):一類別一實例,開給全域存取
圖源:還是我
製程與使用分離,i.e. 終端使用者毋需瞭解生產過程,出張嘴下單就好
生產新品時,不必修改上下游程式碼
工廠程式碼改不到,所以有問題一定是你的問題
還記得上次訂披薩的流程嗎?看菜單 → 下單 → 取貨 → 享用
裡面可有個步驟,需要知道披薩製作過程?
除非你是廚師,否則一般人吃 100 次披薩,也不會掌握製作細節
同理,買車時僅需選輛買得起、好看、實用的車,我哪管車怎麼蹦出來的?
造工廠的藍圖,亦即工廠的工廠
製程各步驟拆開,由不同製造者 (builder)負責
大工程拆成小任務,自然容易許多
有種情況是,一個類別 (class)為了接不同數量的參數 (parameter),而建立多個建構函式 (constructors),屬於一種反面模式 (anti-pattern),設計上應避免
製造者模式 (Builder pattern):拆分製造程序,各步驟由一個製造者負責
圖源:仍是我How old am I? 怎麼老是我
模組 (module)或類別 (class)應外包「所需」功能,而非自產自銷
車靠引擎跑 → 車
依賴引擎
為手機「裝」電池,而非把電池做在手機上,如同現代無良手機品牌們
→ 將電池注入手機
依賴性注入 (Dependency Injection Pattern):外包功能,而非自產自銷
圖源:當然,只會是我
最後,來看看軟體服務常用的設計形式
服務拆三層:使用者 - 伺服器 - 資料庫
3層式架構 (3-tier architercture):用戶端 - 伺服器端 - 資料庫端
圖源:不是我還會是誰?
既然已拆成三層,就能依此結構延伸出:
模型-視圖-控制器 (Model-View-Controller)
模型-視圖-展示器 (Model-View-Presenter)
模型-視圖-視圖模型 (Model-View-ViewModel)
這東西還真拗口
可獨立做單元測試 (unit test),GUI 介面非必要
有點混亂了嗎?
想像你進入咖啡廳,看著菜單選品項:菜單就是視圖 (view)
最後來個統整:
MVC、MVP、MVVM 統整
製表人:我自己
內容如有錯誤,歡迎交流指教
更瞭解系統設計了吧?
感謝您浪費時間撥冗閱讀,咱們下篇見!