成為詩人後可能不需要刻意地按照某種模式去創作,但成為詩人前他們一定是認真地研究過成百上千的唐詩宋詞、古今名句。 ...
《大話設計模式》
作者:程傑
前言
成為 詩人 後 可能 不需要 刻意 地 按照 某種 模式 去 創作, 但 成為 詩人 前 他們 一定 是 認真 地 研究 過 成百上千 的 唐詩 宋詞、 古今 名句。
第 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
建造者模式 主要 是 用於 創建 一些 複雜 的 對象, 這些 對象 內部 構建 間的 建造 順序 通常 是 穩定 的, 但對 象 內部 的 構建 通常 面臨 著 複雜 的 變化。
第 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 號 選手 建造者( Bu