設計模式之美

王爭(@小爭哥) 著

  • 出版商: 人民郵電
  • 出版日期: 2022-06-01
  • 定價: $599
  • 售價: 7.5$449
  • 語言: 簡體中文
  • 頁數: 242
  • ISBN: 7115584745
  • ISBN-13: 9787115584748
  • 相關分類: Design Pattern
  • 相關翻譯: 設計模式之美 (繁中版)
  • 立即出貨 (庫存 < 4)

  • 設計模式之美-preview-1
  • 設計模式之美-preview-2
設計模式之美-preview-1

買這商品的人也買了...

商品描述

 本書結合真實項目案例,從面向對象編程範式、設計原則、代碼規範、重構技巧和設計模式5個方面詳細介紹如何編寫高質量代碼。

  第1章為概述,簡單介紹了本書涉及的各個模塊,以及各個模塊之間的聯系;第2章介紹面向對象編程範式;第3章介紹設計原則;第4章介紹代碼規範;第5章介紹重構技巧;第6章介紹創建型設計模式;第7章介紹結構型設計模式;第8章介紹行為型設計模式。

  本書可以作為各類研發工程師的學習、進階讀物,也可以作為高等院校相關專業師生的教學和學慣用書,以及電腦培訓學校的教材。

作者簡介

王争,前Google工程师,《数据结构与算法之美》书籍作者,热衷技术分享,gzh:小争哥。热爱分享,对数据结构、设计模式和算法有很好的的研究。

量身打造

目錄大綱

第 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