重構與模式
讀完《重構——改善既有程式碼的設計》和《重構與模式》,有了些許感想,先與大家分享一下。當我們已經對設計模式倒背如流時,卻往往發現在實際程式碼編寫中有生搬硬套的感覺。設計模式是前人經驗的總結,直接拿來用合不合適呢?這讓我想起了大學一位老師告訴我們的一條學習的道路“知識,理論,智慧”。設計模式是很一種優雅的“智慧”,但對於我們初學者來說還僅僅是留存於文字的“知識”。把“知識”融合到自己的開發中,在不斷探索和總結中形成自己“理論”,再應用到實際中,那麼這才是是真正屬於我們自己的“智慧”。重構恰恰是由“知識”到“理論”的必經之路,而書中的各種重構方法無疑是這條路上清晰的路標。
程式碼的壞味道大家一看都不會陌生,絕對是在我們的程式設計中如影隨形的,現在把相應的重構方法和設計模式總結出來,方便自己參考查閱,也希望對大家有所幫助。
友情提示:下面所列出的不是公式,不是別的重構方法不能用,也不是非要重構到相應的設計模式,因為不論是重構還是應用設計模式,一切的目的都是為了軟體構架的“優雅”,而不是炫耀技術。另外,兩位作者在描述重構步驟的時候,都不斷重複著“編譯並通過測試”的步驟,這無疑是在強調測試的重要性,和重構的遞進性,切不可一措而蹴。
程式碼的壞味道 | 一般重構方法 | 使用模式重構 |
重複程式碼 | 提煉方法 提取類 方法上移 替換演算法 鏈構造方法 |
構造Template Method 以Composite取代一/多之分 引入Null Object 用Adapter統一介面 用Fatory Method引入多型建立 |
過長方法 | 提取方法 組合方法 以查詢取代臨時變數 引入引數物件 保持物件完整 |
轉移聚集操作到Vistor 以Strategy取代條件邏輯 以Command取代條件排程程式 轉移聚集操作到Collecting Parameter |
過長引數列 | 以方法取代引數 引入引數物件 保持物件完整 |
|
條件邏輯過度複雜 | 分解條件式 合併條件式 合併重複的條件片段 移除控制標記 以衛語句取代巢狀條件式 以多型取代條件式 引入斷言 |
以Strategy取代條件邏輯 轉移裝飾功能到Decorator 以State取代狀態改變條件語句 引入Null Object |
分支語句 | 提取方法 轉移方法 以子類取代型別程式碼 以多型取代條件式 已明確方法取代引數 |
以State/Strategy取代型別程式碼 引入Null Object 以Command替換條件排程程式 轉移聚集操作到Visitor |
基本型別迷戀 程式程式碼過於依賴基本型別(int,string,double,array等低層次語言要素) |
以物件取代資料值 以型別取代型別程式碼 以子類取代型別程式碼 提取類 引入引數物件 以物件取代陣列 |
以State取代狀態改變條件語句 以Strategy取代條件邏輯 以Composite取代隱含樹 以Interpreter取代隱式語言 轉移裝飾功能到Decorator 用Builder封裝Composite |
資料泥團 在類的欄位和引數列中,總是一起出現的資料 |
提取類 引入引數物件 保持物件完整 |
|
令人迷惑的臨時欄位 | 提取類 | 引入Null Object |
組合爆炸 許多段程式碼使用不同種類或數量的資料或物件做同樣的事情(例如使用特定條件和資料庫查詢) |
以Interpreter取代隱式語言 | |
過大類 | 提取類 提取子類 提取介面 複製被監視資料 |
以Command取代條件排程程式 以State取代狀態改變條件語句 以Interpreter取代隱式語言 |
冗贅類 不再做很多工作或沒有用的類 |
摺疊繼承關係 內聯Singleton |
|
不恰當的暴露 在客戶程式碼中不應看到類的欄位和方法,卻是公開可見的 |
封裝欄位 封裝群集 移除設定方法 隱藏方法 |
用Factory封裝類 |
發散式變化 類經常因為不同的原因在不同方向上發生變化,顯然是違反了單一職責原則 |
提取類 | |
霰彈式修改 如果遇到變化,必須在不同的類中作出相應的修改 |
轉移方法 轉移欄位 內聯類 |
將建立知識搬移到Factory |
依戀情結 方法對於某個類的興趣高過對自己所處的宿主類 |
轉移方法 提取方法 |
引入Strategy 引入Visitor |
平行繼承體系 當為一個類增加一個子類時,也必須在另一個類中增加一個相應的子類 |
轉移方法 轉移欄位 |
|
誇誇其談未來性 | 摺疊繼承關係 內聯類 移除引數 移除方法 |
|
過度耦合的訊息連 不斷的向一個物件索求另一個物件 |
隱藏委託 提取方法 轉移方法 |
使用抽象引入Chain Of Responsibility |
中間轉手人 類介面中有很多方法都委託給其他類 |
移除中間轉手人 內聯方法 以繼承取代委託 |
|
狎暱關係 類之間彼此依賴於其private成員 |
轉移方法 將雙向關聯改為單向 提取類 隱藏委託 以繼承取代委託 |
|
異曲同工的類 | 重新命名方法 轉移方法 提取超類 |
用Adapter統一介面 |
不完善的程式庫類 | 引入外加方法 引入本地擴充套件 |
用Adapter統一介面 用Facade封裝類 |
純稚的資料類 只擁有欄位的資料類 |
封裝欄位 封裝集合 移除設定方法 轉移方法 隱藏方法 |
|
被拒絕的遺贈 繼承父類時,子類想要選擇繼承的成員 |
以委託取代繼承 | |
過多的註釋 為糟糕的程式碼寫大量的註釋 |
使用一起重構方法,使方法本身達到自說明的效果,讓註釋顯得多餘 | |
怪異解決方案 在同一系統中使用不同的方式解決同一問題 |
替換演算法 | 用Adapter統一介面 |
相關文章
- 重構與模式(二)——釋出訂閱模式與中介者模式實際使用模式
- 重構與模式系列(一)簡化函式模式函式
- 重構 - 觀察者模式模式
- 重構模式(一)---- 介紹模式
- iOS MVP模式重構實踐iOSMVP模式
- FE.BASE-前端設計模式、編碼與重構筆記前端設計模式筆記
- iOS模式分析 使用介面卡模式重構TableViewiOS模式View
- 用Lambda重構責任模式鏈模式
- 使用Lambdas重構工廠設計模式設計模式
- 重構到觀察者模式 Refactor to Observer Pattern模式Server
- 程式碼重構與單元測試——“提取方法”重構(三)
- 重構、重新架構、再設計與重寫的區別架構
- 重構模式(二)---- 為什麼要 Refactoring模式
- 系統重構的道與術
- 重建模與重構的區別
- 使用命令模式重構播放器控制條模式播放器
- 使用策略模式重構電商折扣和支付場景模式
- 記一次重構,策略模式替換if else模式
- 從例項談OOP、工廠模式和重構模式
- 重構 JAVA 聊天室 —— CS 模式的簡單架構實現Java模式架構
- Repractise架構篇一: CMS的重構與演進架構
- Repractise架構篇一:CMS的重構與演進架構
- CSS程式碼重構與優化之路CSS優化
- 程式碼重構與單元測試——重構1的單元測試(四)
- 如何重構上帝式大物件反模式 - Cameron McKenzie物件模式
- 使用函數語言程式設計重構模板模式函數程式設計模式
- 使用職責鏈模式來重構你的程式碼模式
- 低程式碼平臺搭建CRM 加速重構業務模式模式
- 重構模式(四)---- 合理、勇敢地運用Refactoring模式
- 從重構的角度學習bridge設計模式設計模式
- 程式碼重構--大話重構
- 程式碼重構與單元測試——對方法的引數進行重構(五)
- 重構
- 程式碼重構與單元測試(一)
- 網路重構的進展與挑戰
- CSS程式碼重構與最佳化之路CSS
- Java 8 重構傳統設計模式,是真的優雅!Java設計模式
- 重構複雜條件的規則設計模式 - levelup設計模式