预购商品
书目分类
特别推荐
本書結合真實項目案例,從面向對象編程範式、設計原則、代碼規範、重構技巧和設計模式5個方面詳細介紹如何編寫高質量代碼。 第1章為概述,簡單介紹了本書涉及的各個模塊,以及各個模塊之間的聯繫;第2章介紹面向對象編程範式;第3章介紹設計原則;第4章介紹代碼規範;第5章介紹重構技巧;第6章介紹創建型設計模式;第7章介紹結構型設計模式;第8章介紹行為型設計模式。 本書可以作為各類研發工程師的學習、進階讀物,也可以作為高等院校相關專業師生的教學和學習用書,以及計算機培訓學校的教材。 王爭(@小爭哥),前Google工程師,《數據結構與算法之美》書籍作者,熱衷技術分享,公眾號:小爭哥。熱愛分享,對數據結構、設計模式和算法有很好的的研究。
第1章 概述 1 1.1 為什麼學習代碼設計 2 1.1.1 編寫高品質的代碼 2 1.1.2 應對複雜代碼的開發 2 1.1.3 程式師的基本功 3 1.1.4 職場發展的必#備技能 4 1.1.5 思考題 4 1.2 如何評價代碼品質 4 1.2.1 可維護性(maintainability) 5 1.2.2 可讀性(readability) 6 1.2.3 可擴展性(extensibility) 6 1.2.4 靈活性(flexibility) 6 1.2.5 簡潔性(simplicity) 7 1.2.6 可複用性(reusability) 7 1.2.7 可測試性(testability) 7 1.2.8 思考題 8 1.3 如何寫出高品質代碼 8 1.3.1 物件導向 8 1.3.2 設計原則 8 1.3.3 設計模式 9 1.3.4 代碼規範 9 1.3.5 重構技巧 10 1.3.6 思考題 11 1.4 如何避免過度設計 11 1.4.1 代碼設計的初衷是提高代碼品質 11 1.4.2 代碼設計的原則是“先有問題,後有方案” 12 1.4.3 代碼設計的應用場景是複雜代碼 12 1.4.4 持續重構可有效避免過度設計 12 1.4.5 不要脫離具體的場景談代碼設計 13 1.4.6 思考題 13 第2章 物件導向程式設計範式 14 2.1 當我們在談論物件導向時,到底在談論什麼 15 2.1.1 物件導向程式設計和物件導向程式設計語言 15 2.1.2 非嚴格定義的物件導向程式設計語言 16 2.1.3 物件導向分析和物件導向設計 16 2.1.4 關於UML的說明 17 2.1.5 思考題 17 2.2 封裝、抽象、繼承和多態為何而生 17 2.2.1 封裝(encapsulation) 18 2.2.2 抽象(abstraction) 20 2.2.3 繼承(inheritance) 21 2.2.4 多態(polymorphism) 22 2.2.5 思考題 25 2.3 如何進行物件導向分析、物件導向設計和物件導向程式設計 25 2.3.1 案例介紹和難點剖析 25 2.3.2 如何進行物件導向分析 26 2.3.3 如何進行物件導向設計 28 2.3.4 如何進行物件導向程式設計 34 2.3.5 思考題 35 2.4 物件導向程式設計與面向過程程式設計和函數式程式設計之間的區別 35 2.4.1 面向過程程式設計 36 2.4.2 物件導向程式設計和面向過程程式設計的對比 38 2.4.3 函數式程式設計 40 2.4.4 物件導向程式設計和函數式程式設計的對比 44 2.4.5 思考題 44 2.5 哪些代碼看似物件導向程式設計風格,實則面向過程程式設計風格 45 2.5.1 濫用getter、setter方法 45 2.5.2 濫用全域變數和全域方法 47 2.5.3 定義資料和方法分離的類 49 2.5.4 思考題 50 2.6 基於“貧血”模型的傳統開發模式是否違背OOP 51 2.6.1 基於“貧血”模型的傳統開發模式 51 2.6.2 基於“充血”模型的DDD開發模式 52 2.6.3 兩種開發模式的應用對比 53 2.6.4 基於“貧血”模型的傳統開發模式被廣泛應用的原因 57 2.6.5 基於“充血”模型的DDD開發模式的應用場景 58 2.6.6 思考題 59 2.7 介面和抽象類別:如何使用普通類類比介面和抽象類別 59 2.7.1 抽象類別和介面的定義與區別 59 2.7.2 抽象類別和介面存在的意義 62 2.7.3 類比實現抽象類別和介面 64 2.7.4 抽象類別和介面的應用場景 65 2.7.5 思考題 65 2.8 基於介面而非實現程式設計:有沒有必要為每個類都定義介面 65 2.8.1 介面的多種理解方式 66 2.8.2 設計思想實戰應用 66 2.8.3 避免濫用介面 69 2.8.4 思考題 69 2.9 組合優於繼承:什麼情況下可以使用繼承 70 2.9.1 為什麼不#使用繼承 70 2.9.2 相比繼承,組合有哪些優勢 72 2.9.3 如何決定是使用組合還是使用繼承 73 2.9.4 思考題 74 第3章 設計原則 75 3.1 單一職責原則:如何判定某個類的職責是否單一 76 3.1.1 單一職責原則的定義和解讀 76 3.1.2 如何判斷類的職責是否單一 76 3.1.3 類的職責是否越細化越好 78 3.1.4 思考題 79 3.2 開閉原則:只要修改代碼,就一定違反開閉原則嗎 79 3.2.1 如何理解“對擴展開放、對修改關閉” 80 3.2.2 修改代碼就意味著違反開閉原則嗎 83 3.2.3 如何做到“對擴展開放、對修改關閉” 84 3.2.4 如何在專案中靈活應用開閉原則 85 3.2.5 思考題 86 3.3 裡氏替換原則:什麼樣的代碼才算違反裡氏替換原則 86 3.3.1 裡氏替換原則的定義 86 3.3.2 裡氏替換原則與多態的區別 88 3.3.3 違反裡氏替換原則的反模式 89 3.3.4 思考題 89 3.4 介面隔離原則:如何理解該原則中的“介面” 89 3.4.1 把“介面”理解為一組API或函數 90 3.4.2 把“介面”理解為單個API或函數 91 3.4.3 把“介面”理解為OOP中的介面概念 92 3.4.4 思考題 96 3.5 依賴反轉原則:依賴反轉與控制反轉、依賴注入有何關係 97 3.5.1 控制反轉(IoC) 97 3.5.2 依賴注入(DI) 98 3.5.3 依賴注入框架(DIFramework) 99 3.5.4 依賴反轉原則(DIP) 100 3.5.5 思考題 100 3.6 KISS原則和YAGNI原則:二者是一回事嗎 100 3.6.1 KISS原則的定義和解讀 101 3.6.2 代碼並非行數越少越簡單 101 3.6.3 代碼複雜不一定違反KISS原則 103 3.6.4 如何寫出滿足KISS原則的代碼 104 3.6.5 YAGNI原則和KISS原則的區別 104 3.6.6 思考題 104 3.7 DRY原則:相同的兩段代碼就一定違反DRY原則嗎 104 3.7.1 代碼邏輯重複 105 3.7.2 功能(語義)重複 106 3.7.3 代碼執行重複 107 3.7.4 代碼的複用性 109 3.7.5 思考題 110 3.8 LoD:如何實現代碼的“高內聚、低耦合” 110 3.8.1 何為“高內聚、低耦合” 110 3.8.2 LoD的定義描述 111 3.8.3 定義解讀與代碼示例一 112 3.8.4 定義解讀與代碼示例二 114 3.8.5 思考題 116 第4章 代碼規範 117 4.1 命名與注釋:如何精准命名和編寫注釋 118 4.1.1 長命名和短命名哪個更好 118 4.1.2 利用上下文資訊簡化命名 118 4.1.3 利用業務詞彙表統一命名 118 4.1.4 命名既要精准又要抽象 119 4.1.5 注釋應該包含哪些內容 119 4.1.6 注釋並非越多越好 120 4.1.7 思考題 120 4.2 代碼風格:與其爭論標準,不如團隊統一 121 4.2.1 類、函數多大才合適 121 4.2.2 一行代碼多長才合適 121 4.2.3 善用空行分割代碼塊 121 4.2.4 是四格縮進還是兩格縮進 122 4.2.5 左大括弧是否要另起一行 122 4.2.6 類中成員的排列順序 122 4.2.7 思考題 123 4.3 程式設計技巧:小技巧,大作用,一招提高代碼的可讀性 123 4.3.1 將複雜的代碼模組化 123 4.3.2 避免函數的參數過多 124 4.3.3 移除函數中的flag參數 125 4.3.4 移除嵌套過深的代碼 126 4.3.5 學會使用解釋性變數 128 4.3.6 思考題 129 第5章 重構技巧 130 5.1 重構四要素:目的、物件、時機和方法 131 5.1.1 重構的目的:為什麼重構(why) 131 5.1.2 重構的對象:到底重構什麼(what) 131 5.1.3 重構的時機:什麼時候重構(when) 132 5.1.4 重構的方法:應該如何重構(how) 132 5.1.5 思考題 133 5.2 單元測試:保證重構不出錯的有效手段 133 5.2.1 什麼是單元測試 133 5.2.2 為什麼要編寫單元測試代碼 135 5.2.3 如何設計單元測試 136 5.2.4 為什麼單元測試落地困難 138 5.2.5 思考題 139 5.3 代碼的可測試性:如何編寫可測試代碼 139 5.3.1 編寫可測試代碼的方法 139 5.3.2 常見不可測試代碼示例 146 5.3.3 思考題 147 5.4 解耦:哪些方法可以用來解耦代碼 147 5.4.1 為何解耦如此重要 147 5.4.2 如何判斷代碼是否需要解耦 148 5.4.3 如何給代碼解耦 148 5.4.4 思考題 150 5.5 重構案例:將ID生成器代碼從“能用”重構為“好用” 150 5.5.1 ID生成器需求背景 150 5.5.2 “湊合能用”的代碼實現 151 5.5.3 如何發現代碼的品質問題 152 5.5.4 第1輪重構:提高代碼的可讀性 153 5.5.5 第二輪重構:提高代碼的可測試性 155 5.5.6 第三輪重構:編寫單元測試代碼 156 5.5.7 第四輪重構:重構異常處理邏輯 158 5.5.8 思考題 165 第6章 創建型設計模式 166 6.1 單例模式(上):為什麼不#在專案中使用單例模式 167 6.1.1 單例模式的定義 167 6.1.2 單例模式的實現方法 167 6.1.3 單例模式的應用:日誌寫入 170 6.1.4 單例模式的弊端 173 6.1.5 單例模式的替代方案 175 6.1.6 思考題 176 6.2 單例模式(下):如何設計實現一個分散式單例模式 177 6.2.1 單例模式的唯#一性 177 6.2.2 執行緒唯#一的單例模式 177 6.2.3 集群環境下的單例模式 178 6.2.4 多例模式 179 6.2.5 思考題 180 6.3 工廠模式(上):如何解耦複雜物件的創建和使用 180 6.3.1 簡單工廠模式(SimpleFactoryPattern) 181 6.3.2 工廠方法模式(FactoryMethodPattern) 183 6.3.3 抽象工廠模式(AbstractFactoryPattern) 186 6.3.4 工廠模式的應用場景總結 187 6.3.5 思考題 187 6.4 工廠模式(下):如何設計實現一個依賴注入容器 188 6.4.1 DI容器與工廠模式的區別 188 6.4.2 DI容器的核心功能 188 6.4.3 DI容器的設計與實現 190 6.4.4 思考題 194 6.5 建造者模式:什麼情況下必須用建造者模式創建物件 194 6.5.1 使用構造函數創建物件 194 6.5.2 使用setter方法為成員變數賦值 195 6.5.3 使用建造者模式做參數校驗 196 6.5.4 建造者模式在Guava中的應用 198 6.5.5 建造者模式與工廠模式的區別 200 6.5.6 思考題 200 6.6 原型模式:如何快速複製(clone)一個雜湊表 200 6.6.1 原型模式的定義 200 6.6.2 原型模式的應用舉例 201 6.6.3 原型模式的實現方式:深拷貝和淺拷貝 203 6.6.4 思考題 206 第7章 結構型設計模式 208 7.1 代理模式:代理模式在RPC、緩存和監控等場景中的應用 209 7.1.1 基於介面實現代理模式 209 7.1.2 基於繼承實現代理模式 211 7.1.3 基於反射實現動態代理 211 7.1.4 代理模式的各種應用場景 212 7.1.5 思考題 213 7.2 裝飾器模式:剖析JavaIO類庫的底層設計思想 213 7.2.1 JavaIO類庫的“奇怪”用法 213 7.2.2 基於繼承的設計方案 215 7.2.3 基於裝飾器模式的設計方案 215 7.2.4 思考題 219 7.3 適配器模式:如何利用適配器模式解決代碼的不相容問題 219 7.3.1 類適配器和對象適配器 219 7.3.2 適配器模式的5種應用場景 221 7.3.3 適配器模式在Java日誌中的應用 224 7.3.4 Wrapper設計模式 226 7.3.5 思考題 230 7.4 橋接模式:如何將M×N的繼承關係簡化為M+N的組合關係 230 7.4.1 橋接模式的定義 230 7.4.2 橋接模式解決繼承“爆#炸”問題 230 7.4.3 思考題 231 7.5 門面模式:如何設計介面以兼顧介面的易用性和通用性 231 7.5.1 門面模式和介面設計 231 7.5.2 利用門面模式提高介面易用性 232 7.5.3 利用門面模式提高介面性能 232 7.5.4 利用門面模式解決事務問題 232 7.5.5 思考題 233 7.6 組合模式:一種應用在樹形結構上的特殊設計模式 233 7.6.1 組合模式的應用一:目錄樹 233 7.6.2 組合模式的應用二:人力樹 237 7.6.3 思考題 239 7.7 享元模式:如何利用享元模式降低系統的記憶體開銷 239 7.7.1 享元模式在棋牌遊戲中的應用 239 7.7.2 享元模式在文字編輯器中的應用 242 7.7.3 享元模式在JavaInteger中的應用 244 7.7.4 享元模式在JavaString中的應用 247 7.7.5 享元模式與單例模式、緩存、物件集區的區別 248 7.7.6 思考題 248 第8章 行為型設計模式 249 8.1 觀察者模式:如何實現一個非同步非阻塞的EventBus框架 250 8.1.1 觀察者模式的定義 250 8.1.2 觀察者模式的代碼實現 250 8.1.3 觀察者模式存在的意義 251 8.1.4 觀察者模式的應用場景 253 8.1.5 非同步非阻塞觀察者模式 254 8.1.6 EventBus框架功能介紹 255 8.1.7 從零開始實現EventBus框架 257 8.1.8 思考題 261 8.2 範本方法模式(上):範本方法模式在JDK、Servlet、JUnit中的應用 261 8.2.1 範本方法模式的定義與實現 261 8.2.2 範本方法模式的作用一:複用 262 8.2.3 範本方法模式的作用二:擴展 264 8.2.4 思考題 266 8.3 範本方法模式(下):範本方法模式與回檔有何區別和聯繫 267 8.3.1 回檔的原理與實現 267 8.3.2 應用示例一:JdbcTemplate 268 8.3.3 應用示例二:setClickListener() 270 8.3.4 應用示例三:addShutdownHook() 271 8.3.5 範本方法模式與回檔的區別 272 8.3.6 思考題 273 8.4 策略模式:如何避免冗長的if-else和switch-case語句 273 8.4.1 策略模式的定義與實現 273 8.4.2 利用策略模式替代分支判斷 275 8.4.3 策略模式的應用舉例:對檔中的內容進行排序 277 8.4.4 避免策略模式誤用 281 8.4.5 思考題 281 8.5 職責鏈模式:框架中的篩檢程式、攔截器和外掛程式是如何實現的 282 8.5.1 職責鏈模式的定義和實現 282 8.5.2 職責鏈模式在敏感詞過濾中的應用 286 8.5.3 職責鏈模式在ServletFilter中的應用 288 8.5.4 職責鏈模式在SpringInterceptor中的應用 290 8.5.5 職責鏈模式在MyBatisPlugin中的應用 293 8.5.6 思考題 297 8.6 狀態模式:遊戲和工作流引擎中常用的狀態機是如何實現的 297 8.6.1 什麼是有限狀態機 298 8.6.2 狀態機實現方式一:分支判斷法 300 8.6.3 狀態機實現方式二:查表法 301 8.6.4 狀態機實現方式三:狀態模式 303 8.6.5 思考題 306 8.7 反覆運算器模式(上):為什麼要用反覆運算器遍歷集合 306 8.7.1 反覆運算器模式的定義和實現 307 8.7.2 遍歷集合的3種方法 309 8.7.3 反覆運算器遍歷集合的問題 310 8.7.4 反覆運算器遍歷集合的問題的解決方案 311 8.7.5 思考題 315 8.8 反覆運算器模式(下):如何實現一個支持快照功能的反覆運算器 315 8.8.1 支援快照功能的反覆運算器 315 8.8.2 設計思路一:基於多副本 316 8.8.3 設計思路二:基於時間戳記 317 8.8.4 思考題 319 8.9 訪問者模式:為什麼支援雙分派的程式設計語言不需要訪問者模式 320 8.9.1 “發明”訪問者模式 320 8.9.2 雙分派(DoubleDispatch) 328 8.9.3 思考題 330 8.10 備忘錄模式:如何優雅地實現資料防丟失、撤銷和恢復功能 330 8.10.1 備忘錄模式的定義與實現 331 8.10.2 優化備忘錄模式的時間和空間開銷 333 8.10.3 思考題 334 8.11 命令模式:如何設計實現基於命令模式的手遊服務器 334 8.11.1 命令模式的定義 334 8.11.2 命令模式的應用:手遊服務器 335 8.11.3 命令模式與策略模式的區別 336 8.11.4 思考題 337 8.12 解譯器模式:如何設計實現一個自訂介面告警規則的功能 337 8.12.1 解譯器模式的定義 337 8.12.2 解譯器模式的應用:運算式計算 337 8.12.3 解譯器模式的應用:規則引擎 340 8.12.4 思考題 343 8.13 仲介模式:什麼時候使用仲介模式?什麼時候使用觀察者模式? 343 8.13.1 仲介模式的定義和實現 343 8.13.2 仲介模式與觀察者模式的區別 344 8.13.3 思考題 344"
最近浏览商品
客服公告
热门活动
订阅电子报