[讀書筆記] 《大話設計模式》

来源:https://www.cnblogs.com/weiliuhong/archive/2020/03/19/note-big-talk-design-mode.html
-Advertisement-
Play Games

成為詩人後可能不需要刻意地按照某種模式去創作,但成為詩人前他們一定是認真地研究過成百上千的唐詩宋詞、古今名句。 ...


 

《大話設計模式》

作者:程傑

前言

成為 詩人 後 可能 不需要 刻意 地 按照 某種 模式 去 創作, 但 成為 詩人 前 他們 一定 是 認真 地 研究 過 成百上千 的 唐詩 宋詞、 古今 名句。 

 

第 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 號 選手 建造者( Bu

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • BFC是什麼? BFC(Block Fomatting Context)為塊級格式化上下文的的簡稱。 簡單點說,把BFC看成一個渲染區域或者容器,在BFC這個容器內部的的元素無論如何佈局都不會影響其外部的元素。 並且BFC還有它自己的一些特性,下麵會說到。 BFC模式的形成條件如下(滿足以下任意一條 ...
  • 網站是用的kindeditor編輯器,今天測試上傳視頻功能,提示說上傳失敗,容量超出 打開upload_json.php 修改$max_size $max_size = 100000000; 成功上傳視頻後,發現生成的格式是embed,而且前臺並不能顯示播放 於是決定將原來系統中的embed標記更改 ...
  • 很多人不明白同樣身為web前端工程師,可為什麼薪資待遇卻是大不相同,web更註重的在於技術。那麼初級web前端應該懂什麼?零基礎入門web前端應該學什麼? 零基礎入門web前端 初級web前端應該懂什麼 可以把前端工程師分為了入門、初級、中級、高級這四個級別,入門指的是瞭解什麼是前端(前端到底是什麼 ...
  • router-view是一個 functional 組件,渲染路徑匹配到的視圖組件。<router-view> 渲染的組件還可以內嵌自己的 <router-view>,根據嵌套路徑,渲染嵌套組件 它只有一個名為name的props,這個name還有個預設值,就是default,一般情況下,我們不用傳 ...
  • [toc] 領域驅動設計 運用領域模型 綁定模型和實現 聰明的項目組成員花費了幾個月的時間進行仔細的研究並且開發出了詳盡的領域模型(類圖)。然而對類圖研究不能讓我深入地瞭解該應用程式的代碼和設計,這讓我備感困擾。當開發人員開始實現應用程式時,他們很快就發現,儘管分析人員說得頭頭是道,他們依然無法將這 ...
  • 一、程式結構分析 第一次作業 1.設計構思與自我評價 第一次作業難度不是太高,只需要解析由常數、冪函數簡單組合的表達式。其中每一項都可以看做coef*x**index的固定形式,建立包含coef,index兩個Biginteger屬性的Term類作為最基本的數據結構,並且實現單項求導的方法。在Ter ...
  • 1、Spring是什麼? Spring是一個輕量級的IoC和AOP容器框架。是為Java應用程式提供基礎性服務的一套框架,目的是用於簡化企業應用程式的開發,它使得開發者只需要關心業務需求。常見的配置方式有三種:基於XML的配置、基於註解的配置、基於Java的配置。 主要由以下幾個模塊組成: Spri ...
  • SpringMVC的工作原理圖: SpringMVC流程 1、 用戶發送請求至前端控制器DispatcherServlet。 2、 DispatcherServlet收到請求調用HandlerMapping處理器映射器。 3、 處理器映射器找到具體的處理器(可以根據xml配置、註解進行查找),生成處 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...