《設計模式之美》是2022年人民郵電出版社出版的圖書,作者是王爭(@小爭哥)。
基本介紹
- 中文名:設計模式之美
- 作者:王爭(@小爭哥)
- 出版時間:2022年1月
- 出版社:人民郵電出版社
- ISBN:9787115584748
- 定價:99 元
- 開本:16 開
- 裝幀:平裝
內容簡介,圖書目錄,作者簡介,
內容簡介
本書首先,講解了設計模式知識的基礎知識,幫助讀者梳理最重要、最常用的七大代碼評判標準,帶讀者認識設計模式的框架;其次,詳細講解面向對象、設計原則、編碼規範、重構技巧等基礎編碼知識,每一個知識點分別通過“理論篇”來精講,通過“實戰篇”帶讀者進行套用,通過“總結篇”複習鞏固所學知識;第三,精講23種經典設計模式,幫讀者搞懂每一種設計模式的原理、核心思想和套用場景,並告訴讀者如何避免過度設計和設計不足,徹底掌握設計模式相關的所有知識;最後,剖析了5個常用開源框架用到的設計模式、原則和思想,並通過完整的分析、設計和實現過程,手把手帶讀者完成3個實戰項目,將學過的理論知識套用到實戰中。本書適合程式設計師、設計模式愛好者閱讀,也適合大專院校相關專業的師生學習。
圖書目錄
第 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 依賴注入框架(DI Framework) 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 第 一輪重構:提高代碼的可讀性 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 簡單工廠模式(Simple Factory Pattern) 181
6.3.2 工廠方法模式(Factory Method Pattern) 183
6.3.3 抽象工廠模式(Abstract Factory Pattern) 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 裝飾器模式:剖析Java IO類庫的底層設計思想 213
7.2.1 Java IO類庫的“奇怪”用法 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 享元模式在Java Integer中的套用 244
7.7.4 享元模式在Java String中的套用 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 職責鏈模式在Servlet Filter中的套用 288
8.5.4 職責鏈模式在Spring Interceptor中的套用 290
8.5.5 職責鏈模式在MyBatis Plugin中的套用 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 雙分派(Double Dispatch) 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
作者簡介
王爭,前Google工程師,《數據結構與算法之美》書籍作者,熱衷技術分享,gzh:小爭哥。熱愛分享,對數據結構、設計模式和算法有很好的的研究。