《大話設計模式》
作者:程杰

前言
成為 詩人 后 可能 不需要 刻意 地 按照 某種 模式 去 創作, 但 成為 詩人 前 他們 一定 是 認真 地 研究 過 成百上千 的 唐詩 宋詞、 古今 名句,
第 1 章 代碼無錯就是優?—— 簡單工廠模式
1.5 活字印刷,面向物件 > 位置 584
“第一, 要 改, 只需 更改 要 改之 字, 此為 可維護; 第二, 這些 字 并非 用完 這次 就 無用, 完全可以 在后 來的 印刷 中 重復 使用, 此 乃 可復用; 第三, 此 詩 若要 加 字, 只需 另 刻字 加入 即可, 這是 可擴展; 第四, 字 的 排列 其實 可能 是 豎排 可能 是 橫排, 此時 只需 將 活字 移動 就可 做到 滿足 排列 需求, 此 是 靈活性好,”
1.10 簡單工廠模式 > 位置 671
簡單工廠模式, 也就是說, 到底 要 實體 化 誰, 將來 會不會 增加 實體 化 的 物件, 比如 增加 開 根 運算, 這是 很容易 變化 的 地方, 應該 考慮 用 一個 單獨 的 類 來做 這個 創造 實體 的 程序, 這就 是 工廠(備注:先用父類宣告物件,再看情況決定用哪個子類實體化物件),
1.11 UML 類圖 > 位置 689
UML 類 圖 圖示 樣 例

注意 前面 的 符號,’+‘ 表示 public,’–‘ 表示 private,’#‘ 表示 protected,
繼承 關系 用 空心 三角形 + 實線 來 表示,
實作 介面 用 空心 三角形 + 虛線 來 表示,
當 一個 類’ 知道’ 另一個 類 時(備注:類里面有另一個類的物件), 可以 用 關聯( association), 關聯 關系 用 實線 箭頭 來 表示,
聚合 表示 一種 弱 的’ 擁有’ 關系(備注:一個類中有另一個類的物件集合), 體現 的 是 A 物件 可以 包含 B 物件, 但 B 物件 不是 A 物件 的 一部分,聚合 關系 用 空心 的 菱形 + 實線 箭頭 來 表示,”
合成( Composition, 也有 翻譯 成’ 組合’ 的) 是一 種 強的’ 擁有’ 關系, 體現 了 嚴格 的 部分 和 整體 的 關系, 部分 和 整體 的 生命 周期 一樣,(備注:整體類初始化時同時構造部分類的物件作為屬性) ,合成 關系 用 實心 的 菱形 + 實線 箭頭 來 表示,
另外, 你會 注意到 合成 關系 的 連線 兩端 還有 一個 數字’ 1′ 和 數字’ 2’, 這 被稱為 基數, 表明 這 一端 的 類 可以 有幾個 實體, 很 顯然, 一個 鳥 應該 有兩 只 翅膀, 如果 一個 類 可能 有無 數個 實體, 則 就用’ n’ 來 表示, 關聯 關系、 聚合 關系 也可以 有 基數 的,
依賴 關系( Dependency)(備注:建構式以依賴的物件作為引數), 用 虛線 箭頭 來 表示,
第 2 章 商場促銷 —— 策略模式
2.4 策略模式 > 位置 777
策略模式( Strategy), 策略 模式 定義 了 演算法 家族, 分別 封裝 起來, 讓 它們 之間 可以 互相 替換, 此 模式 讓 演算法 的 變化, 不會 影響 到 使用 演算法 的 客戶,

2.7 策略模式決議 > 位置 821
策略 模式 是一 種 定義 一系列 演算法 的 方法, 從 概念上 來看, 所有這些 演算法 完成 的 都是 相同 的 作業, 只是 實作 不同, 它 可以 以 相同 的 方式 呼叫 所有 的 演算法, 減少 了 各種 演算法 類 與 使用 演算法 類 之間 的 耦合 [DPE],
另外 一個 策略 模式 的 優點 是 簡化 了 單元 測驗, 因為 每個 演算法 都有 自己的 類, 可以 通過 自己的 介面 單獨 測驗 [DPE],
策略 模式 封裝了變化:
當 不同 的 行為 堆砌 在 一個 類 中 時, 就很 難 避免 使用 條件 陳述句 來 選擇 合適 的 行為, 將 這些 行為 封裝 在 一個 個 獨立 的 Strategy 類 中, 可以 在使 用 這些 行 為的 類 中 消除 條件 陳述句 [DP],
策略 模式 就是 用來 封裝 演算法 的, 但在 實踐中, 我們 發現 可以 用 它來 封裝 幾乎 任何 型別 的 規則, 只要 在 分析 程序中 聽到 需要 在不同時間應用不同的業務規則, 就可以 考慮 使用 策略 模式 處理 這種 變化 的 可能性 [DPE]”,
第 3 章 拍攝 UFO—— 單一職責原則
3.4 單一職責原則 > 位置 879
單一職責原則, 意思 就是說, 功能 要 單一?
哈, 可以 簡單 地 這么 理解, 它的 準確 解釋 是, 就 一個 類 而言, 應該 僅有 一個 引起 它 變化 的 原因 [ASD],
3.5 方塊游戲的設計 > 位置 903
如果 一個 類 承擔 的 職責 過多, 就 等于 把這 些 職責 耦合 在一起, 一個 職責 的 變化 可能 會 削弱 或者 抑制 這個 類 完成 其他 職責 的 能力, 這種 耦合 會 導致 脆弱 的 設計, 當 變化 發生 時, 設計 會 遭受 到 意想不到 的 破壞 [ASD],
第 4 章 考研求職兩不誤 —— 開放 – 封閉原則
4.1 考研失敗 > 位置 958
一個 國家, 兩種制度, 這 在政治上, 是 偉大 的 發明 哦, 在 軟體 設計 模式 中, 這種 不能 修改, 但可以 擴展 的 思想 也是 最重要的 一種 設計 原則, 它 就是 開放 – 封閉 原則( The Open- Closeed Principle, 簡稱 OCP) 或 叫開 – 閉 原則,”
4.2 開放 – 封閉原則 > 位置 962
這個 原則 其實 是有 兩個 特征, 一個 是說’ 對于 擴展 是 開放 的( Open for extension)’, 另一個 是說’ 對于 更改 是 封閉 的( Closed for modification)'[ASD],”
4.3 何時應對變化 > 位置 994
在 我們 最初 撰寫 代碼 時, 假設 變化 不會 發生, 當 變化 發生 時, 我們 就 創建 抽象 來 隔離 以后 發生 的 同類 變化 [ASD],
第 5 章 會修電腦不會修收音機?—— 依賴倒轉原則
5.3 依賴倒轉原則 > 位置 1083
依賴 倒轉 原則, 原話 解釋 是 抽象 不應該 依賴 細節, 細節 應該 依賴于 抽象, 這 話 繞口, 說白 了, 就是 要 針對 介面 編程, 不要 對 實作 編程,
5.4 里氏代換原則 > 位置 1105
子類 型 必須 能夠 替換 掉 它們 的 父 型別 [ASD],
由于 有 里氏代換原則, 才使 得 開放 – 封閉 成為 了 可能,
由于 子 型別 的 可替換 性 才使 得 使用 父 類 型別 的 模塊 在 無需 修改 的 情況下 就可以 擴展,
再回 過頭 來看 依賴倒轉原則, 高層 模塊 不應該 依賴 低層 模塊, 兩個 都應 該 依賴 抽象,
依賴 倒轉 其實 就是 誰也 不要 依靠 誰, 除了 約定 的 介面,
5.5 修收音機 > 位置 1131
依賴 倒轉 其實 可以 說是 面向物件設計 的 標志, 用 哪種 語言 來 撰寫 程式 不重要, 如果 撰寫 時 考慮 的 都是 如何 針對 抽象 編程 而 不是 針對 細節 編程, 即 程式 中 所有 的 依賴 關系 都是 終止 于 抽象 類 或者 介面, 那就 是 面向 物件 的 設計, 反之 那就 是 程序 化 的 設計 了 [ASD],”
第 6 章 穿什么有這么重要?—— 裝飾模式
6.4 裝飾模式 > 位置 1229
裝飾模式(Decorator),動態地給一個物件添加一些額外的職責,就增加功能來說,裝飾模式比生成子類更為靈活,[DP]
裝飾 模式( Decorator) 結構圖:

6.6 裝飾模式總結 > 位置 1281
裝飾模式 是 為 已有 功能 動態 地 添加 更多 功能 的 一種 方式,
把 每個 要 裝飾 的 功能 放在 單獨 的 類 中, 并 讓 這個 類 包裝 它 所要 裝飾 的 物件, 因此, 當 需要 執行 特殊 行為 時, 客戶 代碼 就可以 在 運行時 根據 需要 有選擇 地、 按 順序 地 使用 裝飾 功能 包裝 物件 了 [DP],
6.6 裝飾模式總結 > 位置 1289
裝飾 模式 的 優點 我總 結下 來就 是, 把 類 中的 裝飾 功能 從 類 中 搬移 去除, 這樣 可以 簡化 原 有的 類,
更大 的 好處 就是 有效地 把 類 的 核心 職責 和 裝飾 功能 區分 開了, 而且 可以 去除 相關 類 中 重復 的 裝飾 邏輯,”
第 7 章 為別人做嫁衣 —— 代理模式
7.5 代理模式 > 位置 1378
代理模式(Proxy),為其他物件提供一種代理以控制對這個物件的訪問,[DP]
代理 模式( Proxy) 結構圖 :

7.6 代理模式應用 > 位置 1394
代理 模式 都用 在 一些 什么 場合 呢?
一般來說 分為 幾種, 第一, 遠程代理, 也就是 為 一個 物件 在 不同 的 地址 空間 提供 區域 代表, 這樣 可以 隱藏 一個 物件 存在 于 不同 地址 空間 的 事實 [DP],
WebService 在. NET 中的 應用 :
在 應用 程式 的 專案 中 加入 一個 Web 參考, 參考 一個 WebService, 此時 會在 專案 中 生成 一個 WebReference 的 檔案夾 和 一些 檔案, 其實 它們 就是 代理, 這就 使得 客戶 端 程式 呼叫 代理 就可以 解決 遠程 訪問 的 問題,
第二 種 應用 是 虛擬代理, 是 根據 需要 創建 開銷 很大 的 物件, 通過 它來 存放 實體 化 需要 很長 時間 的 真實 物件 [DP], 這樣 就可以 達到 性能 的 最優化, 比如說 你 打開 一個 很大 的 HTML 網頁 時, 里面 可能 有很 多的 文字 和 圖片, 但 你 還是 可以 很快 打開 它, 此時 你 所 看到 的 是 所有 的 文字, 但 圖片 卻是 一張 一張 地下 載 后才 能看 到, 那些 未 打開 的 圖片 框, 就是 通過 虛擬 代理 來 替代 了 真實 的 圖片, 此時 代理 存盤 了 真實 圖片 的 路徑 和 尺寸,
第三 種 應用 是 安全代理, 用來 控制 真實 物件 訪問 時 的 權限 [DP], 一般 用于 物件 應該 有 不同 的 訪問 權限 的 時候,
第 四種 是 智能指引, 是指 當 呼叫 真實 的 物件 時, 代理 處理 另外 一些 事 [DP], 如 計算 真實 物件 的 參考 次數, 這樣 當 該 物件 沒有 參考 時, 可以 自動 釋放 它; 或當 第一次 參考 一個 持久 物件 時, 將它 裝入 記憶體; 或在 訪問 一個 實際 物件 前, 檢查 是否 已經 鎖定 它, 以 確保 其他 物件 不能 改變 它, 它們 都是 通過 代理 在 訪問 一個 物件 時 附加 一些 內務 處理,
代理 模式 其實 就是 在 訪問 物件 時 引入 一定程度 的 間接性, 因為 這種 間接 性, 可以 附加 多種 用途,
第 8 章 雷鋒依然在人間 —— 工廠方法模式
8.4 簡單工廠 vs. 工廠方法 > 位置 1472
簡單工廠 模式 的 最大 優點 在于 工廠 類 中 包含 了 必要 的 邏輯 判斷, 根據 客戶 端 的 選擇 條件 動態 實體 化 相關 的 類, 對于 客戶 端來 說, 去 除了 與 具體 產品 的 依賴,
工廠方法模式(Factory Method),定義一個用于創建物件的介面,讓子類決定實體化哪一個類,工廠方法使一個類的實體化延遲到其子類,[DP]
工廠 方法 模式( Factory Method) 結構圖:

把工廠類抽象出一個介面, 這個 介面 只有 一個 方法, 就是 創建 抽象 產品 的 工廠 方法, 然后, 所 有的 要 生產 具體 類 的 工廠, 就去 實作 這個 介面, 這樣, 一個 簡單 工廠 模式 的 工廠 類, 變成 了 一個 工廠 抽象 介面 和 多個 具體 生成 物件 的 工廠,
工廠方法 把 簡單 工廠 的 內部 邏輯 判斷 移到 了 客戶 端 代碼 來 進行, 你 想要 加 功能, 本來 是 改 工廠 類 的, 而 現在 是 修改 客戶 端!”
8.5 雷鋒工廠 > 位置 1530
工廠 方法 克服 了 簡單 工廠 違背 開放 – 封閉 原則 的 缺點, 又 保持 了 封裝 物件 創建 程序 的 優點,
它們 都是 集中 封裝 了 物件 的 創建, 使得 要 更換 物件 時, 不需 要做 大的 改動 就可 實作, 降低 了 客戶 程式 與 產品 物件 的 耦合, 工廠 方法 模式 是 簡單 工廠 模式 的 進一步 抽象 和 推廣, 由于 使 用了 多 態 性, 工廠 方法 模式 保持 了 簡單 工廠 模式 的 優點, 而且 克服 了 它的 缺點, 但 缺點 是 由于 每 加 一個 產品, 就 需要 加 一個 產品 工廠 的 類, 增加 了 額外 的 開發 量,
第 9 章 簡歷復印 —— 原型模式
9.3 原型模式 > 位置 1598
原型模式(Prototype),用原型實體指定創建物件的種類,并且通過拷貝這些原型創建新的物件,[DP]
原型 模式( Prototype) 結構圖 :

原型 模式 其實 就是 從 一個 物件 再創 建 另外 一個 可 定制 的 物件, 而且 不需 知道 任何 創建 的 細節,
因為 克隆 實在 是 太 常用 了, 所以. NET 在 System 命名 空間 中 提供 了 ICloneable 介面, 其中 就是 唯一 的 一個 方法 Clone(), 這樣 你就 只需 要 實作 這個 介面 就可以 完成 原型 模式 了,
9.5 淺復制與深復制 > 位置 1622
MemberwiseClone() 方法 是 這樣, 如果 欄位 是 值 型別 的, 則 對 該 欄位 執行 逐 位 復制, 如果 欄位 是 參考 型別, 則 復制 參考 但不 復制 參考 的 物件; 因此, 原始 物件 及其 復本 參考 同一 物件,
9.5 淺復制與深復制 > 位置 1641
淺復制, 被 復制 物件 的 所有 變數 都 含有 與 原來 的 物件 相同 的 值, 而 所有 的 對其 他 物件 的 參考 都 仍然 指向 原來 的 物件,
深復制 把 參考 物件 的 變數 指向 復制 過 的 新 物件, 而 不是 原 有的 被 參考 的 物件,
深 復制 要 深入 到 多少 層, 需要 事先 就 考慮 好, 而且 要 當心 出現 回圈 參考 的 問題, 需要 小心 處理, 這里 比較 復雜, 可以 慢慢 研究,
9.6 簡歷的深復制實作 > 位置 1656
比如說, 資料 集 物件 DataSet, 它 就有 Clone() 方法 和 Copy() 方法, Clone() 方法 用來 復制 DataSet 的 結構, 但不 復制 DataSet 的 資料, 實作 了 原型 模式 的 淺 復制, Copy() 方法 不但 復制 結構, 也 復制 資料, 其實 就是 實作 了 原型 模式 的 深 復制,
第 10 章 考題抄錯會做也白搭 —— 模板方法模式
10.3 提煉代碼 > 位置 1749
當 我們 要 完成 在某 一 細節 層次 一致 的 一個 程序 或 一系列 步驟, 但 其 個別 步驟 在 更 詳細 的 層次 上 的 實作 可能 不 同時, 我們 通常考慮用 模板方法模式 來 處理,
10.4 模板方法模式 > 位置 1763
模板方法模式,定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟,[DP]
模板 方法 模式( TemplateMethod) 結構圖 :

模板 方法 模式 是 通過 把 不變 行為 搬 移到 超 類, 去除 子類 中的 重復 代碼 來 體現 它的 優勢,
當 不 變的 和 可變 的 行為 在 方法 的 子類 實作 中 混合 在一起 的 時候, 不變 的 行為 就會 在 子類 中 重復 出現, 我們 通過 模板 方法 模式 把這 些 行為 搬移 到 單一 的 地方, 這樣 就 幫助 子類 擺脫 重復 的 不變 行為 的 糾纏,
第 11 章 無熟人難辦事?—— 迪米特法則
11.3 迪米特法則 > 位置 1845
迪米特法則(LoD) 也叫 最少 知識 原則,[J& DP]
迪米特法則(LoD),如果兩個類不必彼此直接通信,那么這兩個類就不應當發生直接的相互作用,如果其中一個類需要呼叫另一個類的某一個方法的話,可以通過第三者轉發這個呼叫,[J&DP]
迪 米 特 法則 首先 強調 的 前提 是在 類 的 結構設計 上, 每一個 類 都應當 盡量降低成員的訪問權限 [J& DP], 也就是說, 一個 類 包裝 好 自己的 private 狀態, 不需要 讓 別的 類 知道 的 欄位 或 行為 就不 要 公開,
迪 米 特 法則 其 根本思想, 是 強 調了 類 之 間的 松耦合,
第 12 章 牛市股票還會虧錢?—— 外觀模式
12.1 牛市股票還會虧錢? > 位置 1890
外觀模式, 又叫門面模式,
12.4 外觀模式 > 位置 1909
外觀模式(Facade),為子系統中的一組介面提供一個一致的界面,此模式定義了一個高層介面,這個介面使得這一子系統更加容易使用,[DP]
外觀 模式( Facade) 結構圖 :

對于 面向 物件 有 一定 基礎 的 朋友, 即使 沒有 聽說 過 外觀 模式, 也 完全 有可 能在 很多 時候 使用 它, 因為 它 完美 地 體現 了 依賴倒轉 原則 和 迪米特法則 的 思想, 所以 是非 常常 用的 模式 之一,
12.5 何時使用外觀模式 > 位置 1921
那 外觀 模式 在什么時候使用 最好 呢?
這要 分 三個 階段 來說, 首先, 在 設計初期階段, 應該 要有 意識 的 將 不同 的 兩個 層 分離, 比如 經典 的 三層 架構, 就 需要 考慮 在 資料 訪問 層 和 業務 邏輯 層、 業務 邏輯 層 和 表示 層 的 層 與 層 之間 建立 外觀 Facade, 這樣 可以 為 復雜 的 子系統 提供 一個 簡單 的 介面, 使得 耦合 大大 降低,
其次, 在開發階段, 子系統 往往 因為 不斷 的 重 構 演化 而 變得 越來越 復雜, 大多數 的 模式 使用 時 也都 會 產生 很多 很 小的 類, 這本 是 好事, 但也 給 外部 呼叫 它們 的 用戶 程式 帶來 了 使 用上 的 困難, 增加 外觀 Facade 可以 提供 一個 簡單 的 介面, 減少 它們 之間 的 依賴,
第三, 在 維護 一個 遺留 的 大型 系統 時, 可能 這個 系統 已經 非常 難以 維護 和 擴展 了, 但 因為 它 包含 非常重 要的 功能, 新的 需求 開發 必須 要 依賴于 它, 此時 用 外觀 模式 Facade 也是 非常 合適 的, 你 可 以為 新 系統 開發 一個 外觀 Facade 類, 來 提供 設計 粗糙 或 高度 復雜 的 遺留 代碼 的 比較 清晰 簡單 的 介面, 讓 新 系統 與 Facade 物件 互動, Facade 與 遺留 代碼 互動 所有 復雜 的 作業,[R2P]
第 13 章 好菜每回味不同 —— 建造者模式
13.4 建造者模式 > 位置 2003
建造者(Builder)模式, 又叫 生成器模式,將一個復雜物件的構建與它的表示分離,使得同樣的構建程序可以創建不同的表示,[DP]
13.4 建造者模式 > 位置 2029
建造者 模式 中 一個 很重 要的 類, 指揮者( Director), 用 它來 控制 建造 程序, 也 用 它來 隔離 用戶 與 建造 程序 的 關聯,
13.5 建造者模式決議 > 位置 2045
建造者 模式( Builder) 結構圖 :
建造者模式 主要 是 用于 創建 一些 復雜 的 物件, 這些 物件 內部 構建 間的 建造 順序 通常 是 穩定 的, 但對 象 內部 的 構建 通常 面臨 著 復雜 的 變化,
第 14 章 老板回來,我不知道 —— 觀察者模式
14.5 觀察者模式 > 位置 2167
觀察者模式 又叫 做 發布 – 訂閱(Publish/ Subscribe)模式,
觀察者 模式( Observer) 結構圖 :

Subject 類, 可翻譯 為 主題 或 抽象 通知者, 一般用 一個 抽象 類 或者 一個 介面 實作, 它 把 所有 對 觀察者 物件 的 參考 保存 在 一個 聚集 里, 每個 主題 都可以 有 任何 數量 的 觀察者, 抽象 主題 提供 一個 介面, 可以 增加 和 洗掉 觀察者 物件,
14.5 觀察者模式 > 位置 2178
Observer 類, 抽象 觀察者, 為所 有的 具體 觀察者 定義 一個 介面, 在 得到 主題 的 通知 時 更新 自己, 這個 介面 叫做 更新 介面, 抽象 觀察者 一般用 一個 抽象 類 或者 一個 介面 實作, 更新 介面 通常 包含 一個 Update () 方法, 這個 方法 叫做 更新 方法,
14.6 觀察者模式特點 > 位置 2210
當 一個 物件 的 改變 需要 同時 改變 其他 物件 , 而且 它不 知道 具體 有多 少 物件 有待 改變 時, 應該 考慮 使用 觀察者 模式,
觀察者 模式 所做 的 作業 其實 就是 在 解除耦合, 讓 耦合 的 雙方 都 依賴于抽象, 而 不是 依賴于 具體, 從而 使得 各自 的 變化 都不 會 影響 另 一邊 的 變化, 這 實在 是 依賴倒轉 原則 的 最佳 體現 呀,
現實 編程 中, 具體 的 觀察者 完全 有可能 是 風馬牛 不相 及 的 類, 但 它們 都 需要 根據 通知者 的 通知 來 做出 Update() 的 操作, 所以 讓 它們 都 實作 下面 這樣 的 一個 介面 就可以 實作 這個 想法 了,
interface Observer { void Update(); }?
14.9 事件委托說明 > 位置 2258
委托 就是 一種 參考 方法 的 型別, 一旦 為 委托 分配 了 方法, 委托 將 與 該 方法 具有 完全 相同 的 行為, 委托 方法 的 使用 可以 像 其他 任何 方法 一樣, 具有 引數 和 回傳 值, 委托 可以 看作 是對 函式 的 抽象, 是 函式 的’ 類’, 委托 的 實體 將 代表 一個 具體 的 函式,
delegate void EventHandler (); 可以 理解 為 宣告 了 一個 特殊 的’ 類’, 而’ public event EventHandler Update;’ 可以 理解 為 宣告 了 一個’ 類’ 的 變數,具體地說, 應該 是 宣告 了 一個 事件 委托 變數 叫’ 更新’,
一個 委托 可以 搭載 多個 方法, 所有 方法 被 依次 喚起, 更重 要的 是, 它可 以使 得 委托 物件 所 搭載 的 方法 并不 需要 屬于 同一個 類,
第 15 章 就不能不換 DB 嗎?—— 抽象工廠模式
15.2 最基本的資料訪問程式 > 位置 2334
工廠方法模式 是 定義 一個 用于 創建 物件 的 介面, 讓 子類 決定 實體 化 哪一個 類,

15.4 用了抽象工廠模式的資料訪問程式 > 位置 2395
涉及 到 多個產品系列 的 問題, 有一個 專門 的 工廠 模式 叫 抽象工廠模式,
15.5 抽象工廠模式 > 位置 2398
抽象工廠模式(Abstract Factory),提供一個創建一系列相關或相互依賴物件的介面,而無需指定它們具體的類,[DP]
抽象 工廠 模式( Abstract Factory) 結構圖 :

15.8 用反射 + 抽象工廠的資料訪問程式 > 位置 2446
本來 依賴注入 是 需要 專門 的 IoC 容器 提供, 比如 Spring. NET, 顯然 當前 這個 程式 不需要 這么 麻煩, 你 只 需要 再 了解 一個 簡單 的. NET 技術’ 反射’ 就可以 了,
反射技術 格式 : Assembly.Load (“程式集名稱”).Createlnstance (“命名空間,類名稱”);
15.9 用反射 + 組態檔實作資料訪問程式 > 位置 2486
所有 在用 簡單 工廠 的 地方, 都可以 考慮 用反射 技術 來 去除 switch 或 if, 解除分支判斷 帶來 的 耦合,
第 16 章 無盡加班何時休 —— 狀態模式
16.5 狀態模式 > 位置 2577
狀態模式 主要 解決 的 是 當 控制 一個 物件 狀態 轉換 的 條件 運算式 過于 復雜 時 的 情況, 把 狀態 的 判斷 邏輯 轉移 到 表示 不同 狀態 的 一系列 類 當中, 可以 把 復雜 的 判斷 邏輯 簡化,
狀態 模式( State) 結構圖 :

16.6 狀態模式好處與用處 > 位置 2588
狀態 模式 的 好處 是將 與 特定 狀態 相關 的 行為 區域化, 并且 將不 同 狀態 的 行為 分割 開來 [DP],
是不是 就是 將 特定 的 狀態 相關 的 行為 都 放入 一個 物件 中, 由于 所有 與 狀態 相關 的 代碼 都存 在于 某個 ConcreteState 中, 所以 通過 定義 新的 子類 可以 很容易 地 增加 新的 狀態 和 轉換 [DP],
說白 了, 這樣做 的 目的 就是 為了 消除 龐大 的 條件 分支 陳述句,
當 一個 物件 的 行為 取決于 它的 狀態, 并且 它 必須 在 運行 時刻 根據 狀態 改變 它的 行為 時, 就可以 考慮 使用 狀態 模式 了, 另外 如果 業務 需求 某項 業務 有多 個 狀態, 通常 都是 一些 列舉 常量, 狀態 的 變化 都是 依靠 大量 的 多分 支 判斷 陳述句 來 實作, 此時 應該 考慮 將 每一種 業務 狀態 定義 為 一個 State 的 子類,
第 17 章 在 NBA 我需要翻譯 —— 配接器模式
17.2 配接器模式 > 位置 2651
配接器模式(Adapter),將一個類的介面轉換成客戶希望的另外一個介面,Adapter 模式使得原本由于介面不兼容而不能一起作業的那些類可以一起作業,[DP]
系統 的 資料 和 行為 都 正確, 但 介面 不符 時, 我們 應該 考慮 用 配接器, 目的 是 使 控制 范圍 之外 的 一個 原有 物件 與 某個 介面 匹配, 配接器 模式 主要 應用于 希望 復 用 一些 現存 的 類, 但是 介面 又與 復 用 環境 要求 不一致 的 情況, 比如 在 需要 對 早期 代碼 復 用 一些 功能 等 應用 上 很有 實際 價值,
配接器 模式( Adapter) 結構圖 :

17.3 何時使用配接器模式 > 位置 2687
通常 是在 軟體 開發 后期 或 維護 期 再考慮 使用
那有 沒有 設計 之初 就 需要 考慮 用 配接器 模式 的 時候?
當然 有, 比如 公司 設計 一 系統 時 考慮 使用 第三方 開發 組件, 而這 個 組件 的 介面 與我 們 自己的 系統 介面 是 不 相同 的, 而 我們 也 完全 沒有 必要 為了 迎合 它 而 改動 自己的 介面, 此時 盡管 是在 開發 的 設計 階段, 也是 可以 考慮 用 配接器 模式 來 解決 介面 不同 的 問題,
第 18 章 如果再回到從前 —— 備忘錄模式
18.3 備忘錄模式 > 位置 2771
備忘錄(Memento):在不破壞封裝性的前提下,捕獲一個物件的內部狀態,并在該物件之外保存這個狀態,這樣以后就可將該物件恢復到原先保存的狀態,[DP]
備忘錄 模式( Memento) 結構圖 :

18.4 備忘錄模式基本代碼 > 位置 2787
是把 要 保存 的 細節 給 封 裝在 了 Memento 中了, 哪 一天 要 更改 保存 的 細節 也不 用 影響 客戶 端 了,
Memento 模式 比較 適用于 功能 比較 復雜 的, 但 需要 維護 或 記錄 屬性 歷史 的 類, 或者 需要 保存 的 屬性 只是 眾多 屬性 中的 一 小部分 時,
如果 在某 個 系統 中 使用 命令 模式 時, 需要 實作 命令 的 撤銷 功能, 那么 命令 模式 可以 使用 備忘錄 模式 來 存盤 可撤銷 操作 的 狀態 [DP],
有時 一些 物件 的 內部 資訊 必須 保存 在 物件 以外 的 地方, 但是 必須 要由 物件 自己 讀取, 這時, 使用 備忘錄 可以 把 復雜 的 物件 內部 資訊 對其 他的 物件 屏蔽 起來 [DP], 從而 可以 恰當 地保 持 封裝 的 邊界,
第 19 章 分公司 = 一部門 —— 組合模式
19.2 組合模式 > 位置 2844
組合模式(Composite),將物件組合成樹形結構以表示’部分 – 整體’的層次結構,組合模式使得用戶對單個物件和組合物件的使用具有一致性,[DP]
組合 模式( Composite) 結構圖:
19.4 何時使用組合模式 > 位置 2866
當你 發現 需求 中 是 體現 部分 與 整體 層次 的 結構 時, 以及 你 希望 用戶 可以 忽略 組合 物件 與 單個 物件 的 不同, 統一 地 使用 組合 結構 中的 所有 物件 時, 就應 該 考慮 用 組合 模式 了,
19.6 組合模式好處 > 位置 2923
組合 模式 讓 客戶 可以 一致 地 使用 組合 結構 和 單個 物件,
第 20 章 想走?可以!先買票 —— 迭代器模式
20.2 迭代器模式 > 位置 2972
迭代器模式(Iterator),提供一種方法順序訪問一個聚合物件中各個元素,而又不暴露該物件的內部表示,[DP]
當你 需要 訪問 一個 聚集 物件, 而且 不管 這些 物件 是什么 都 需要 遍歷 的 時候, 你就 應該 考慮 用 迭代 器 模式,
你 需要 對 聚集 有多 種 方式 遍歷 時, 可以 考慮 用 迭代 器 模式,
迭代 器 模式 為 遍歷 不同 的 聚集 結構 提供 如 開始、 下一個、 是否 結束、 當前 哪 一項 等 統一 的 介面,
不過 現今 來看 迭代 器 模式 實用 價值 遠 不如 學習 價值 大 了, MartinFlower 甚至 在 自己的 網 站上 提出 撤銷 此 模式, 因為 現在 高級 編程 語言 如 C#、 JAVA 等 本身 已經 把這 個 模式 做 在 語言 中了,
哈, foreach in ,另外 還有 像 IEnumerable 介面 也是 為 迭代 器 模式 而 準備 的,
20.3 迭代器實作 > 位置 2987
迭代 器 模式( Iterator) 結構圖:
20.4 .NET 的迭代器實作 > 位置 3009
IEumerator 支持 對 非 泛 型 集合 的 簡單 迭代 介面,

IEnumerable 公開 列舉 數, 該 列舉 數 支持 在 非 泛 型 集合 上進 行 簡單 迭代,
你會 發現, 這 兩個 介面, 特別是 IEumerator 要比 我們 剛才 寫的 抽象 類 Iterator 要 簡潔, 但可 實作 的 功能 卻 一點 不少, 這 其實 也 是對 GoF 的 設計 改良 的 結果,
foreach in 就是 實作 這 兩個 介面 來 實際 回圈 遍歷:
IEnumerator<string> e = a.GetEnumerator();
while(e.MoveNext())
{
Console.WriteLine(“{0} 請買車票 !”, e.Current);
} ?
迭代 器( Iterator) 模式 就是 分離 了 集合 物件 的 遍歷 行為, 抽象 出 一個 迭代 器 類 來 負責, 這樣 既可以 做到 不 暴露 集合 的 內部 結構, 又可 讓 外部 代碼 透明 地 訪問 集合 內部 的 資料,
第 21 章 有些類也需計劃生育 —— 單例模式
21.4 單例模式 > 位置 3103
單例模式(Singleton),保證一個類僅有一個實體,并提供一個訪問它的全域訪問點,[DP]
單 例 模式( Singleton) 結構圖 :

21.4 單例模式 > 位置 3109
“我怎 么 感覺 單 例 有點 像 一個 實用類 的 靜態 方法, 比如. Net 框架 里 的 Math 類, 有很 多數 學 計算 方法, 這 兩者 有 什么 區別 呢?”
“你說 得 沒錯, 它們 之 間的 確 很 類似, 實用 類 通常 也會 采用 私有化 的 構造 方法 來 避免 其 有 實體, 但它 們 還是 有很 多 不同 的, 比如 實用 類 不保 存 狀態, 僅 提供 一些 靜態 方法 或 靜態 屬性 讓你 使用, 而 單例類 是有 狀態 的, 實用 類 不能 用于 繼承 多 態, 而 單 例 雖然 實體 唯一, 卻是 可以 有 子類 來 繼承, 實用 類 只不過是 一些 方法 屬性 的 集合, 而 單 例 卻是 有著 唯一 的 物件 實體, 在 運用 中 還得 仔細 分析 再作 決定 用 哪一種 方式,”
21.5 多執行緒時的單例 > 位置 3115
多 執行緒 的 程式 中, 多個 執行緒 同時, 注意 是 同時 訪問 Singleton 類, 呼叫 GetInstance() 方法, 會有 可能 造成 創建 多個 實體 的,
可以 給 行程 一把 鎖 來 處理, 這里 需要 解釋 一下 lock 陳述句 的 涵義, lock 是 確保 當 一個 執行緒 位于 代碼 的 臨界 區時, 另一個 執行緒 不進 入 臨界 區, 如果 其他 執行緒 試圖 進入 鎖定 的 代碼, 則 它將 一直 等待( 即被 阻止), 直到 該 物件 被 釋放,
21.6 雙重鎖定 > 位置 3126
不用 讓 執行緒 每次 都 加鎖, 而 只是 在 實體 未被 創建 的 時候 再加 鎖 處理, 同時 也能 保證 多 執行緒 的 安全, 這種 做法 被稱為 Double- Check Locking( 雙重 鎖定),
21.7 靜態初始化 > 位置 3136
其實 在 實際 應用 當中, C# 與 公共 語言 運行 庫 也 提供 了 一種’ 靜態初始化‘ 方法, 這種 方法 不需要 開發 人員 顯 式 地 撰寫 執行緒 安全 代碼, 即可 解決 多 執行緒 環境 下 它是 不安全 的 問題,[MSDN]
談不上 更好, 只不過 實作 更簡單, 我們 來看 代碼,

由于 這種 靜態 初始化 的 方式 是在 自己 被 加載 時 就 將 自己 實體 化, 所以 被 形象 地 稱之為 餓漢式單例類, 原先 的 單 例 模式 處理 方式 是 要在 第一次 被 參考 時, 才會 將 自己 實體 化, 所以 就被 稱為 懶漢式單例類,[ J& DP]
由于 餓漢 式, 即 靜態 初始化 的 方式, 它是 類 一 加載 就 實體 化 的 物件, 所以 要 提前 占用 系統 資源, 然而 懶漢 式, 又會 面臨 著 多 執行緒 訪問 的 安全性 問題, 需要 做 雙重 鎖定 這樣 的 處理 才可 以 保證 安全, 所以 到底 使用 哪一種 方式, 取決于 實際 的 需求, 從 C# 語言 角度 來講, 餓漢 式 的 單 例 類 已經 足夠 滿足 我們 的 需求 了,
第 22 章 手機軟體何時統一 —— 橋接模式
22.2 緊耦合的程式演化 > 位置 3237
在 面向 物件 設計 中, 我們 還有 一個 很重 要的 設計 原則, 那就 是 合成 / 聚合復用原則, 即 優先 使用 物件 合成 / 聚合, 而 不是 類 繼承 [DP],
22.3 合成 / 聚合復用原則 > 位置 3239
合成( Composition, 也有 翻譯 成 組合) 和 聚合( Aggregation) 都是 關聯 的 特殊 種類, 聚合 表示 一種 弱 的’ 擁有’ 關系, 體現 的 是 A 物件 可以 包含 B 物件, 但 B 物件 不是 A 物件 的 一部分; 合成 則是 一種 強的’ 擁有’ 關系, 體現 了 嚴格 的 部分 和 整體 的 關系, 部分 和 整體 的 生命 周期 一樣 [DPE],

合成 / 聚合 復 用 原則 的 好處 是, 優先 使用 物件 的 合成 / 聚合 將有 助于 你 保持 每個 類 被 封裝, 并被 集中 在 單個 任務 上, 這樣 類 和 類 繼承 層次 會 保持 較小 規模, 并且 不太 可能 增長 為 不可 控制 的 龐然大物 [DP],
手機 品牌 包含 有手 機 軟體, 但 軟體 并不是 品牌 的 一部分, 所以 它們 之間 是 聚合 關系,
結構圖(下一節用到):

22.4 松耦合的程式 > 位置 3289
兩個 抽象 類 之間 有 什么, 像 什么?
有一個 聚合 線, 哈, 像 一座 橋,” “好, 說得 好, 這個 設計 模式 就 叫做’ 橋 接 模式’,
抽象與它的實作分離, 這 并不 是說, 讓 抽象 類 與其 派生 類 分離, 因為 這 沒有 任何 意義, 實作 指的 是 抽象 類 和 它的 派生 類 用來 實作 自己的 物件 [DPE], 就 剛才 的 例子 而言, 就是 讓’ 手機’ 既可以 按照 品牌 來 分類, 也可以 按照 功能 來 分類,”
22.5 橋接模式 > 位置 3296
由于 實作 的 方式 有 多種, 橋 接 模式 的 核心 意圖 就是 把這 些 實作獨立出來, 讓 它們 各自 地 變化, 這就 使得 每種 實作 的 變化 不會 影響 其他 實作, 從而 達到 應對 變化 的 目的,
22.6 橋接模式基本代碼 > 位置 3299
橋 接 模式( Bridge) 結構圖 :

22.6 橋接模式基本代碼 > 位置 3320
在 發現 我們 需要 多角度去分類實作物件, 而 只用 繼承 會 造成 大量 的 類 增加, 不能 滿足 開放 – 封閉 原則 時, 就 應該 要 考慮 用 橋 接 模式 了,
第 23 章 烤羊肉串引來的思考 —— 命令模式
23.6 命令模式 > 位置 3416
命令模式(Command),將一個請求封裝為一個物件,從而使你可用不同的請求對客戶進行引數化;對請求排隊或記錄請求日志,以及支持可撤銷的操作,[DP]
命令 模式( Command) 結構圖 :

23.7 命令模式作用 > 位置 3435
命令 模式 的 優點:
第一, 它 能 較 容易 地 設計 一個 命令 佇列;
第二, 在 需要 的 情況下, 可以 較 容 易地 將 命令 記入 日志;
第三, 允許 接收 請求 的 一方 決定 是否 要 否決 請求,
第四, 可以 容易 地 實作 對 請求 的 撤銷 和 重做;
第五, 由于 加進 新的 具體 命令 類 不 影響 其 他的 類, 因此 增加 新的 具體 命令 類 很容易,
其實 還有 最 關鍵 的 優點 就是 命令 模式 把 請求 一個 操作 的 物件 與 知道 怎么 執行 一個 操作 的 物件 分割 開,
敏捷開發原則 告訴 我們, 不要 為 代碼 添加 基于 猜測 的、 實際 不需 要的 功能, 如果不 清楚 一個 系統 是否 需要 命令 模式, 一般 就不 要 著急 去 實作 它, 事實上, 在 需要 的 時候 通 過重構 實作 這個 模式 并不 困難, 只有 在 真正 需要 如 撤銷 / 恢復 操作 等 功能 時, 把 原來 的 代碼 重 構 為 命令 模式 才有 意義,[R2P]
第 24 章 加薪非要老總批?—— 職責鏈模式
24.3 職責鏈模式 > 位置 3500
職責鏈模式(Chain of Responsibility):使多個物件都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系,將這個物件連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個物件處理它為止,[DP]
這里 發出 這個 請求 的 客戶 端 并不 知道 這 當中 的 哪一個 物件 最終 處理 這個 請求, 這樣 系統 的 更改 可 以在 不 影響 客戶 端 的 情況下 動態 地 重新 組織 和 分配 責任,
職責 鏈 模式( Chain of Responsibility) 結構圖 :

24.4 職責鏈的好處 > 位置 3515
接收者 和 發送者 都沒 有 對方 的 明確 資訊, 且 鏈 中的 物件 自己 也 并不 知道 鏈 的 結構, 結果是 職責 鏈 可簡化 物件 的 相互 連接, 它們 僅 需 保持 一個 指向 其 后繼者 的 參考, 而 不需 保持 它 所有 的 候選 接受者 的 參考 [DP], 這也 就 大大 降低 了 耦 合度 了,
第 25 章 世界需要和平 —— 中介者模式
25.1 世界需要和平! > 位置 3552
中介者模式 又 叫做 調停者模式,
盡管 將 一個 系統 分割 成 許多 物件 通常 可以 增加 其 可 復 用性, 但是 物件 間 相互 連接 的 激增 又會 降低 其 可 復 用性 了,
是因為 大量 的 連接 使得 一個 物件 不可 能在 沒有 其他 物件 的 支持下 作業, 系統 表現 為 一個 不可分割 的 整體, 所以, 對 系統 的 行為 進行 任何 較大 的 改動 就 十分困難 了,

25.1 世界需要和平! > 位置 3574
通過 中介 者 物件, 可以 將 系統 的 網狀 結構 變成 以 中介 者 為 中心 的 星形結構, 使得 系統 的 結構 不會 因為 新 物件 的 引入 造成 大量 的 修改 作業,

25.2 中介者模式 > 位置 3582
中介者模式(Mediator),用一個中介物件來封裝一系列的物件互動,中介者使各物件不需要顯式地相互參考,從而使其耦合松散,而且可以獨立地改變它們之間的互動,[DP]
中介 者 模式( Mediator) 結構圖 :

25.4 中介者模式優缺點 > 位置 3634
中介 者 模式 很容易 在 系統 中 應用, 也 很容易 在 系統 中 誤用, 當 系統 出現 了’ 多對 多’ 互動 復雜 的 物件 群 時, 不要 急于 使用 中介 者 模式, 而要 先 反思 你的 系統 在 設計 上 是不是 合理,
中介 者 模式 的 優點 來自 集中控制, 其 缺點 也 是它, 使用 時 是要 考慮 清楚 ,
25.4 中介者模式優缺點 > 位置 3658
中介 者 模式 一般應用于 一組 物件 以 定義 良好 但是 復雜 的 方式 進行 通信 的 場合, 以及 想定 制 一個 分布 在 多個 類 中的 行為, 而又 不想 生成 太多 的 子類 的 場合,
第 26 章 專案多也別傻做 —— 享元模式
26.2 享元模式 > 位置 3703
享元模式(Flyweight),運用共享技術有效地支持大量細粒度的物件,[DP]

26.4 內部狀態與外部狀態 > 位置 3742
在 享 元 物件 內部 并且 不會 隨 環境 改變 而 改變 的 共享 部分, 可以 稱 為是 享 元 物件 的 內部 狀態, 而 隨 環境 改變 而 改變 的、 不可以 共享 的 狀態 就是 外部 狀態 了, 事實上, 享 元 模式 可以避免 大量 非常 相似 類 的 開銷, 在 程式設計 中, 有時 需要 生成 大量 細 粒度 的 類 實體 來 表示 資料, 如果 能 發現 這些 實體 除了 幾個 引數 外 基本上 都是 相同 的, 有時 就能 夠受 大幅度 地 減少 需要 實體 化 的 類 的 數量, 如果 能把 那些 引數 移到 類 實體 的 外面, 在 方法 呼叫 時 將它 們 傳遞 進來, 就可以 通過 共享 大幅度 地 減少 單個 實體 的 數目,
26.5 享元模式應用 > 位置 3780
如果 一個 應用 程式 使用 了 大量的物件, 而 大量 的 這些 物件 造成了 很大 的 存盤 開銷 時 就應 該 考慮 使用; 還有 就是 物件 的 大多數 狀態 可以 外部 狀態, 如果 洗掉 物件 的 外部 狀態, 那么 可以 用 相對 較少 的 共享 物件 取代 很多 組 物件, 此時 可以 考慮 使用 享 元 模式,
26.5 享元模式應用 > 位置 3802
使用 享 元 模式 需要 維護 一個 記錄 了 系統 已有 的 所有 享 元 的 串列, 而這 本身 需要 耗費 資源, 另外 享 元 模式 使得 系統 更加 復雜, 為了 使對 象 可以 共享, 需要 將 一些 狀態 外部 化, 這使 得 程式 的 邏輯 復雜化, 因此, 應當 在 有 足夠多的物件 實體 可供 共享 時 才 值得 使用 享 元 模式,
第 27 章 其實你不懂老板的心 —— 解釋器模式
27.2 解釋器模式 > 位置 3834
解釋器模式(interpreter),給定一個語言,定義它的文法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子,[DP]
解釋器 模式 需要 解決 的 是, 如果 一種 特定 型別 的 問題 發生 的 頻率 足夠 高, 那么 可能 就 值得 將 該 問題 的 各個 實體 表述 為 一個 簡單 語言 中的 句子, 這樣 就可以 構建 一個 解釋器, 該 解釋器 通過 解釋 這些 句子 來 解決 該 問題,
所謂 的 解釋器 模式, 正則運算式 就是 它的 一種 應用, 解釋器 為 正 則 運算式 定義 了 一個 文法, 如何 表示 一個 特 定的 正 則 運算式, 以及 如何 解釋 這個 正 則 運算式,
解釋器 模式( interpreter) 結構圖:

27.3 解釋器模式好處 > 位置 3875
當 有一個 語言 需要 解釋執行, 并且 你 可將 該 語言 中的 句子 表示 為 一個 抽象 語法樹 時, 可使用 解釋器 模式,
用了 解釋器 模式, 就 意味著 可以 很容易 地 改變 和 擴展 文法, 因為 該 模式 使用類來表示文法規則, 你 可使用 繼承 來 改變 或 擴展 該文 法, 也比 較 容易 實作 文法, 因為 定義 抽象 語法樹 中 各個 節點 的 類 的 實作 大體 類似, 這些 類 都 易于 直接 撰寫 [DP],
解釋器 模式 也有 不足 的, 解釋器 模式 為 文法 中的 每一 條規 則 至少 定義 了 一個 類, 因此 包含 許多 規則 的 文法 可能 難以 管理 和 維護, 建議 當 文法 非常 復雜 時, 使用 其他 的 技術 如 語法 分析 程式 或 編譯器 生成 器 來 處理 [DP]
第 28 章 男人和女人 —— 訪問者模式
28.5 訪問者模式 > 位置 4062
訪問者模式(Visitor),表示一個作用于某物件結構中的各元素的操作,它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作,[DP]
訪問者 模式( Visitor) 結構圖 :

在這里, Element 就是 我們 的’ 人’ 類, 而 ConcreteElementA 和 ConcreteElementB 就是’ 男人’ 和’ 女人’, Visitor 就是 我們 寫的’ 狀態’ 類, 具體 的 ConcreteVisitor 就是 那些’ 成功’、’ 失敗’、’ 戀愛’ 等等 狀態, 至于 ObjectStructure 就是’ 物件 結構’ 類 了,
28.5 訪問者模式 > 位置 4071
訪問者 模式 適用于 資料 結構 相對 穩定 的 系統,它 把 資料 結構 和 作用于 結構上 的 操作 之間 的 耦合 解脫 開, 使得 操作 集合 可以 相對 自由 地 演化,
訪問者 模式 的 目的 是要 把 處理 從 資料 結構 分離 出來, 很多 系統 可以 按照 演算法 和數 據 結構 分開, 如果 這樣 的 系統 有 比較 穩定 的 資料 結構, 又有 易于 變化 的 演算法 的 話, 使用 訪問者 模式 就是 比較 合適 的, 因為 訪問者 模式 使得 演算法 操作 的 增加 變得 容易, 反之, 如果 這樣 的 系統 的 資料 結構 物件 易于 變化, 經常 要有 新的 資料 物件 增加 進來, 就不 適合 使用 訪問者 模式,
訪問者 模式 的 優點 就是 增加 新的 操作 很容易, 因為 增加 新的 操作 就 意味著 增加 一個 新的 訪問者, 訪問者 模式 將 有關 的 行為 集中 到 一個 訪問者 物件 中,
訪問者 的 缺點 其實 也就是 使 增加 新的 資料 結構 變得 困難 了,
所以 GoF 四人 中的 一個 作者 就 說過:’ 大多 時候 你 并不 需要 訪問者 模式, 但當 一旦 你 需要 訪問者 模式 時, 那就 是真 的 需要 它 了,’ 事實上, 我們 很難 找到 資料 結構 不變化 的 情況, 所以 用 訪問者 模式 的 機會 也就 不太 多了, 這也 就是 為什么 你 談到 男人 女人 對比 時 我很 高興 和你 討論 的 原因, 因為 人類 性別 這樣 的 資料 結構 是 不會 變化 的,
第 29 章 OOTV 杯超級模式大賽 —— 模式總結
29.3 超模大賽開幕式 > 位置 4233
根據 模式 的 特點, 設定 了 三個 類別, 分別 是 創建型模式、 結構型模式 和 行為型模式, 但 由于 有 11 位 選擇 了 行為 型 模式, 人數 過多, 所以 行為 型 模式 又 分 為了 兩 組,
分組 情況:

29.4 創建型模式比賽 > 位置 4247
第一 組 創建 型 選手, 1 號 選手, 抽象 工廠 小姐, 她的 口號 是 提供 一個 創建 一系列 或 相關 依賴 物件 的 介面, 而無 需 指定 它們 具體 的 類,[DP]
1 號 選手 抽象工廠( Abstract Factory):

2 號 選手, 建造者 小姐, 她的 口號 是將 一個 復雜 物件 的 構建 與 它的 表示 分離, 使得 同樣 的 構建 程序 可以 創建 不同 的 表示,[DP]
2 號 選手 建造者( Bulider) :

3 號 選手 工廠 方法 小姐 向我 們 走來, 她 聲稱 定義 一個 用于 創建 物件 的 介面, 讓 子類 決定 實體 化 哪一個 類, 工廠 模式 使 一個 類 的 實體 化 延 遲到 其 子類,[DP]
3 號 選手 工廠方法( Factory Method):

4 號 選手 是 原型 小姐, 她的 意圖 是 用 原型 實體 指定 創建 物件 的 種類, 并且 通過 拷貝 這些 原型 創建 新的 物件,[DP]
4 號 選手 原型( Prototype):

5 號 選手 出場, 單 例 小姐, 她 提倡 簡捷 就是 美, 保證 一個 類 僅有 一個 實體, 并提 供 一個 訪問 它的 全域 訪問 點,[DP]
5 號 選手 單例( Singleton):

29.4 創建型模式比賽 > 位置 4280
創建 型 模式 隱藏 了 這些 類 的 實體 是 如何 被 創建 和 放在 一起, 整個 系統 關于 這些 物件 所 知道 的 是由 抽象 類 所 定義 的 介面, 這樣, 創建 型 模式 在 創建 了 什么、 誰 創建 它、 它是 怎么 被 創建 的, 以及 何時 創建 這些 方面 提供 了 很大 的 靈活性 [DP],
內聚性 描述 的 是一 個例 程 內部 組成部分 之間 相互 聯系 的 緊密 程度, 而 耦合 性 描述 的 是一 個例 程 與其 他 例程 之間 聯系 的 緊密 程度, 軟體 開發 的 目標 應該 是 創建 這樣 的 例程: 內部 完整, 也就是 高內聚, 而 與其 他 例程 之間 的 聯系 則是 小巧、 直接、 可見、 靈活 的, 這 就是 松耦合 [ DPE],
29.4 創建型模式比賽 > 位置 4306
通常 設計 應 該是 從 工廠 方法 開始, 當 設計者 發現 需要 更大 的 靈活性 時, 設計 便會 向 其他 創建 型 模式 演化, 當 設計者 在 設計 標準 之間 進行 權衡 的 時候, 了解 多個 創建 型 模式 可以 給 設計者 更多 的 選擇 余地,
29.5 結構型模式比賽 > 位置 4341
第二 組, 也就是 結構型 模式 組
6 號 選手, 配接器 小姐, 她的 口號 是將 一個 類 的 介面 轉換 成 客戶 希望 的 另外 一個 介面, 配接器 模式 使得 原本 由于 介面 不兼容 而 不能 一起 作業 的 那些 類 可以 一起 作業,[DP]

7 號 選手 叫 橋 接, 橋接 小姐 提倡 的 是將 抽象 部分 與 它的 實作 部分 分離, 使它 們 都可以 獨立 地 變化,

8 號 選手 向我 們 走來, 組合 小姐, 一個 非常 美麗 的 姑娘, 她的 口號 是將 物件 組 合成 樹 形 結構 以 表示’ 部分 – 整體’ 的 層次 結構, 組合 模式 使得 用戶 對 單個 物件 和 組合 物件 的 使用 具有 一致性,[DP]

9 號 選手, 裝飾 小姐, 她的 意圖 非常 簡單, 就是 動態 地 給 一個 物件 添加 一些 額外 的 職責, 就 增加 功能 來說, 裝飾 模式 相比 生成 子類 更加 靈活 [DP], 
10 號 選手 出現 了, 外觀 小姐, 她的 形象 如 她的 名字 一樣 的 棒, 她說 為 子系統 中的 一組 介面 提供 一個 一致 的 界面, 外觀 模式 定義 了 一個 高層 介面, 這個 介面 使得 這一 子系統 更加 容易 使用,[DP]

11 號 選手 是 享元 小姐, 她的 參賽 宣言 為 運用 共享 技術 有效地 支持 大量 細 粒度 的 物件,[DP]

12 號 選手, 代理 小姐 向我 們 走來, 她 聲稱 為 其他 物件 提供 一種 代理 以 控制 對這 個 物件 的 訪問,[DP]

29.5 結構型模式比賽 > 位置 4434
“哦, 各位 來賓, 觀眾 朋友們, 第二 場 結構 型 模式 的 比賽 真是 相當 精彩, 各位 選手 也都 實力 相當, 難分 伯仲, 現在 出現 了’ 橋接’、’ 配接器’、’ 外觀’ 的 比分 均為 兩分 的 相同 情況, 根據 比賽規則, 她們 三位 需要 站上 PK 臺, 進行 PK, 三位 有請,”
“下面 請 三位 各自 說 一說 你 比 其他 兩位 優秀 的 地方, 配接器 小姐 先來,”
配接器 說:” 我 主要 是 為了 解決 兩個 已有 介面 之間 不匹配 的 問題, 我不 需要 考慮 這些 介面 是 怎樣 實作 的, 也不 考慮 它們 各自 可能 會 如何 演化, 我的 這種 方式 不需 要對 兩個 獨立 設計 的 類 中 任一 個 進行 重新 設計, 就 能夠使 它們 協同 作業,[DP]”
“非常好, 下面 有請 橋接 小姐,”
“我 覺得 我和 配接器 小姐 具有 一些 共同 的 特征, 就是 給 另一 物件 提供 一定程度 的 間接 性, 這樣 可以 有利于 系統 的 靈活性, 但 正 所謂 未雨綢繆, 我們 不能 等到 問題 發生了, 再去 考慮 解決問題, 而是 更應該 在 設計 之初 就 想好 應該 如何 做 來 避免 問題 的 發生, 我 通常 是在 設計 之初, 就 對 抽象 介面 與 它的 實作 部分 進行 橋 接, 讓 抽象 與 實作 兩者 可以 獨立 演化, 顯然, 我的 優勢 更 明顯,[ DP]”
“OK, 說 得很 棒, 外觀 小姐, 您有 什么 觀點?”
“首先 我 剛 聽完 兩位 小姐 的 發言, 我 個人 覺得 她們 各自 有 各自 的 優點, 并不 能說 設計 之初 就 一定 比 設計 之后 的 彌補 要好, 事實上, 在 現實 中, 早已 設計 好的 兩個 類, 過后 需要 它們 統一 介面, 整 合為 一 的 事例 也 比比皆是, 因此 橋 接和 配接器 是 被用 于 軟體 生命 周期 的 不同 階段, 針對 的 是不同 的 問題, 談不上 孰 優 孰 劣, 然后, 對于 我 來說, 和 配接器 還有 些 近似, 都是 對現 存 系統 的 封裝, 有 人說 我 其實 就是 另外 一組 物件 的 配接器, 這種 說法 是 不準確 的, 因為 外觀 定義 的 是一 個 新的 介面, 而 配接器 則是 復 用 一個 原有 的 介面, 配接器 是 使 兩個 已有 的 介面 協同 作業, 而外 觀 則是 為 現存 系統 提供 一個 更為 方便 的 訪問 介面, 如果 硬要 說 我是 適配, 那么 配接器 是 用來 適配 物件 的, 而我 則是 用來 適配 整個 子系統 的, 也就是說, 我所 針對 的 物件 的 粒度 更大,[ DP]”
29.6 行為型模式一組比賽 > 位置 4471
第三 組, 也就是 行為型 模式 一組
13 號 選手, 觀察者 小姐 入場, 它的 口號 是 定義 物件 間的 一種 一對 多的 依賴 關系, 當 一個 物件 的 狀態 發生 改變 時, 所有 依賴于 它的 物件 都得 到 通知 并被 自動 更新,[DP]

14 號 選手, 模板方法 小姐, 她 提倡 定義 一個 操作 的 演算法 骨架, 而將 一些 步驟 延遲 到 子類 中, 模板 方法 使得 子類 可以 不改 變 一個 演算法 的 結構 即可 重 定義 該 演算法 的 某些 特定 步驟,[DP]

15 號 選手 是 命令 小姐, 它 覺得 應該 將 一個 請求 封裝 為 一個 物件, 從 而使 你 可用 不同 的 請求 對 客戶 進行 引數 化; 可以 對 請求 排隊 或 記錄 請求 日志, 以及 支持 可撤銷 的 操作,[DP]

16 號 是 狀態 小姐, 她說 允許 一個 物件 在 其內 部 狀態 改變 時 改變 它的 行為, 讓 物件 看起來 似乎 修改 了 它的 類,[DP]

17 號 選手, 職責鏈 小姐, 她 一直 認為 使 多個 物件 都有 機會 處理 請求, 從而 避免 請求 的 發送者 和 接收者 之間 的 耦合 關系, 將 這些 物件 連成 一條 鏈, 并 沿著 這條 鏈 傳遞 該 請求, 直到 有一個 物件 處理 它 為止,[DP]

29.7 行為型模式二組比賽 > 位置 4563
18 號 選手, 解釋器 小姐, 它 聲稱 給定 一個 語言, 定義 它的 文法 的 一種 表示, 并 定義 一個 解釋器, 這個 解釋器 使用 該 表示 來 解釋 語言 中的 句子,[DP]

19 號 選手 是 中介者 小姐, 她說 她是 用 一個 中介 物件 來 封裝 一系列 的 物件 互動, 中介 者 使 各 對像 不需要 顯 式 地 相互 參考, 從而 使其 耦合 松散, 而且 可以 獨立 地 改變 它們 之間 的 互動,[DP]

20 號 小姐 向我 們 走來, 訪問者 小姐, 她 表示 一個 作用于 某 物件 結構 中的 各 元素 的 操作, 它 使 你 可以 在 不 改變 各 元素 的 類 的 前提 下定義 作用于 這些 元素 的 新 操作,[DP]

21 號 小姐 是 策略, 一個 可愛 的 姑娘, 她的 意圖 是 定義 一系列 的 演算法, 把 它們 一個 個 封裝 起來, 并且 使 它們 可 相互 替換, 本 模式 使得 演算法 可 獨立 于 使用 它的 客戶 而 變化,[DP]

22 號 選手, 備忘錄 小姐, 她說 在 不破 壞 封裝 性的 前提下, 捕獲 一個 物件 的 內部 狀態, 并在 該 物件 之外 保存 這個 狀態, 這樣 以后 就 可將 該 物件 恢復 到 原先 保存 的 狀態,[DP]

選手, 23 號, 迭代器 小姐, 她說, 提供 一種 方法 順序 訪問 一個 聚合 物件 中 各個 元素, 而又 不需 暴露 該 物件 的 內部 表示,[DP]

29.8 決賽 > 位置 4647
好的, 現在 我們 比賽 已經 進入 了 最高潮, 23 位 選手, 經過 激烈 的 比拼, 現在 選出 了 五位 選手 將 站在 PK 臺上, 來 決定 今天 冠 亞 季軍 的 歸屬, 她們 分別 是…… 工廠 方法 小姐、 外觀 小姐、 觀察者 小姐、 策略 小姐 和 觀眾 朋友 選出 的 可愛 的 配接器 小姐,

29.8 決賽 > 位置 4720
面向 物件 設計 模式 體現 的 就是 抽象 的 思想, 類 是什么, 類 是對 物件 的 抽象, 抽象類 呢, 其實 就 是對 類 的 抽象, 那 介面 呢, 說白 了 就是 對 行為 的 抽象,
附錄 A 培訓實習生 —— 面向物件基礎
A.7 繼承 > 位置 4895
子類 從 它的 父 類 中 繼承 的 成員 有方法、 域、 屬性、 事件、 索引 指示器, 但對 于 構造 方法, 有 一些 特殊, 它不 能被 繼承, 只能 被 呼叫, 對于 呼叫 父 類 的 成員, 可 以用 base 關鍵字,
A.8 多型 > 位置 4935
多 態 表示 不同 的 物件 可以 執行 相同 的 動作, 但要 通過 它們 自己的 實作 代碼 來 執行,
A.8 多型 > 位置 4940
這 里面 有 幾點 注意, 第一, 子類 以 父類 的 身份 出現,
第二、 子類 在 作業 時 以 自己的 方式 來 實作,
第三、 子類 以 父 類 的 身份 出現 時, 子類 特有 的 屬性 和 方法 不可以 使用,
A.8 多型 > 位置 4960
多 態 的 原理 是 當 方法 被 呼叫 時, 無論 物件 是否 被 轉換 為 其父 類, 都 只有 位于 物件 繼承 鏈 最末端 的 方法 實作 會被 呼叫, 也就是說, 虛 方法 是 按照 其 運行時 型別 而非 編譯 時 型別 進行 動態 綁 定調 用的,[AMNFP]
A.10 抽象類 > 位置 4991
我們 完全可以 考慮 把 實體 化 沒有 任何 意義 的 父 類, 改成 抽象 類, 同樣 的, 對于 Animal 類 的 getShoutSound 方法, 其實 方法 體 沒有 任何 意義, 所以 可以 將 virtual 修飾 符 改為 abstract, 使之 成為 抽象 方法, C# 允許 把 類 和 方法 宣告 為 abstract, 即 抽象 類 和 抽象 方法,
抽象類 需要 注意 幾點:
第一, 抽象 類 不能 實體 化;
第二, 抽象 方法 是 必須 被子 類 重寫 的 方法,其實 抽象 方法 可以 被 看成 是 沒有 實作 體 的 虛 方法;
第三, 如 果類 中 包含 抽象 方法, 那么 類 就必須 定義 為 抽象 類, 不論 是否 還 包含 其他 一般 方法,
A.11 介面 > 位置 5019
介面 是把 隱式 公共 方法 和 屬性 組合 起來, 以 封裝 特定 功能 的 一個 集合, 一旦 類 實作 了 介面, 類 就可以 支持 介面 所指 定的 所有 屬性 和 成員, 宣告 介面 在 語 法上 與 宣告 抽象 類 完全 相同, 但不 允許 提供 介面 中 任何 成員 的 執行 方式, 所以 介面 不能 實體 化, 不能 有 構造 方法 和 欄位; 不能 有 修飾 符, 比如 public、 private 等; 不能 宣告 虛擬 的 或 靜態 的 等, 還有 實作 介面 的 類 就必須 要 實作 介面 中的 所有 方法 和 屬性,
A.11 介面 > 位置 5040
抽象 類 可以 給出 一些 成員 的 實作, 介面 卻不 包含 成員 的 實作, 抽象 類 的 抽象 成員 可被 子類 部分 實作, 介面 的 成員 需要 實作 類 完全 實作, 一個 類 只能 繼承 一個 抽象 類, 但可 實作 多個 介面 等等, 但這 些 都是 從 兩者 的 形態 上去 區分 的,
我 覺得 還有 三點 是 能 幫助 我們 去 區分 抽象 類 和 介面 的,
第一, 類 是對 物件 的 抽象; 抽象 類 是對 類 的 抽象; 介面 是對 行為 的 抽象, 介面 是對 類 的 區域( 行為) 進行 的 抽象, 而 抽象 類 是對 類 整體( 欄位、 屬性、 方法) 的 抽象, 如果 只 關注 行為 抽象, 那么 也可以 認為 介面 就是 抽象 類,
第二, 如果 行為 跨越 不 同類 的 物件, 可使用 介面; 對于 一些 相 似的 類 物件, 用 繼承 抽象 類,
第三, 從 設計 角度 講, 抽象 類 是 從 子類 中 發現 了 公共 的 東西, 泛 化 出 父 類, 然后 子類 繼承 父 類, 而 介面 是 根本 不知 子類 的 存在, 方法 如何 實作 還不 確認, 預先 定義,
抽象 類 是 自 底 而上 抽象 出來 的, 而 介面 則是 自 頂 向下 設計 出來 的,
A.14 委托與事件 > 位置 5133
委托 是對 函式 的 封裝, 可以 當作 給 方法 的 特征 指定 一個 名稱, 而 事件 則是 委托 的 一種 特殊 形式, 當 發生 有意義 的 事情 時, 事件 物件 處理 通知 程序 [PC#], 事件 其實 就是 設計 模式 中 觀察者模式 在. NET 中的 一種 實作 方式,

同步首發:http://dlgcy.com/note-big-talk-design-mode/
PDF下載地址:https://545c.com/file/1680845-430023488
打賞
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/19645.html
標籤:設計模式
上一篇:設計模式的原則和法則
下一篇:Spring面試題詳細版
