設計模式問答2

jopen 9年前發布 | 20K 次閱讀 設計模式

介紹

這是設計模式問答1的連載。在這個系列,我們將覆蓋到解釋器、迭代器、調停者、備忘錄和觀察者模式。

如果你還沒有閱讀過我之前的系列,你可以隨時從下面開始

什么是解釋器模式?

解釋器模式允許我們將語法解釋為代碼解決方案。好了,這意味著什么?語法會被映射到類,并形成解決方案。 舉個例子,7 – 2能夠被映射到“clsMinus”類。一句話,解釋器模式為我們提供了一種解決方案,這個方案指導如何編寫一個解析語法并執行代碼的解釋器。下面是一個 解釋器的簡單例子,它能夠按照我們提供的日期格式語法,將日期解釋為對應的代碼,并輸入正確的結果。

 設計模式問答2

日期語法

讓我們開始做圖“日期語法”中所示的日期格式的解釋器。在開始之前,我們要先理解一下解釋器模式中不同的組件,然后再來處理映射。上下文部分包含數據,而邏輯部分包含將上下文中數據轉換成可讀格式的轉換邏輯。

 設計模式問答2

上下文和邏輯

讓我們看一下日期格式的語法是怎么定義的。定義任何語法的第一步,是把語法分解成小的邏輯組件。圖“語法映射與類 的映射”展示了怎么識別這些組件,以及怎么映射到處理這部分語法的邏輯類上面。我們已經把日期格式打斷成了4個組件,分別是月、日、年和分隔符。對這4個 組件,我們將分別定義包含圖中展示的邏輯的類。然后,我們將為日期格式的不同組件創建不同的類。

 設計模式問答2

語法映射與類的映射

前 面說過,有兩種類,一種是包含邏輯的表達式類,另一種是包含數據的上下文類,如圖“表達式和上下文類”中所示。我們定義了不同類中的表達式解析算法,這些 類都從公共接口“ClsAbstractExpression”派生,并實現了“Evaluate”方法。“Evaluate”方法接收包含數據的上下文 類作為參數;它根據表達式邏輯來解析數據。“ClsYearExpression”實例將“YYYY”替換成年份值,而 “ClsMonthExpression”將“MM”替換成月份值,以此類推。

 設計模式問答2

解釋器類圖

 設計模式問答2

表達式和上下文類

現在,我們有了單獨的表達式解析邏輯類,然后我們來看看客戶端會如何使用這個邏輯。客戶端首先把日期語法格式傳遞給 上下文類。依據日期格式,我們依次向集合中添加表達式實例。如果我們找到了“DD”,我們就添加一個“ClsDayExpression”實例;如果我們 找到了“MM”,就添加一個“ClsMonthExpression”實例,等等。最后,我們只需要遍歷集合,并調用“Evaluate”函數。所有的 “Evaluate”函數執行完之后,我們就顯示結果。

 設計模式問答2

客戶端解釋器邏輯

你能解釋迭代器模式嗎?

迭代器模式允許在不暴露內部代碼實現的情況下,順序訪問每個元素。讓我們來理解一下。假設你有一個記錄集合,你需要順序遍歷 每條記錄,并且需要保持當前訪問的位置,那么你需要的正是迭代器模式。這是最普通的設計模式,你會在不知不覺中用到它。在某些程度上,當你使用 “foreach”(它允許我們逐個元素地訪問一個集合)時,你就已經在使用迭代器模式了。

 設計模式問答2

迭代器業務邏輯

在圖“迭代器業務邏輯”中,我們使用 “clsIterator”類來存放顧客類的集合。我們在“clsIterator”類內部,定義了一個數組,和一個名稱為“FillObjects”的 方法,這個方法用來加載數組的內容。顧客集合數組是私有的,顧客的數據可以通過數組的下標來訪問。因此我們定義了一組公有函數,包含 “getByIndex”(通過指定下表來訪問),“Prev”(得到集合中前一個顧客數據),“Next”(得到集合中下一個顧客數 據),“getFirst”(得到集合中第一個顧客數據),“getLast”(得到集合中最后一個顧客數據)。

我們只對客戶端暴露這些函數。這些函數小心的順序遍歷集合,并能夠記憶當前遍歷的索引。

下面的圖“客戶遍歷邏輯”說明了該如何使用類“clsIterator”的實例“ObjIterator”,顯示下一個、前一個、最后一個、第一個,以及通過索引顯示顧客數據。

 設計模式問答2

客戶遍歷邏輯

你能解釋調停者模式嗎?

大多數時候,項目中組件間的通訊都很復雜。因此組件間的邏輯關系也變得異常復雜。調停者模式幫助對象間用不互相關聯的方式來通訊,從而使復雜度最小化。

 設計模式問答2

調停者模式示例

讓我們考慮圖“調停者模式示例”,它描述了一個需要使用調停者模式的真實場景。它是一個非常用戶友好的接口。它有3個典型的場景。

場景1:當用戶在文本框中輸入時,應該使添加和清除按鈕可用。一旦當文本框中沒有文字時,應該禁用添加和清除按鈕。

 設計模式問答2

場景1

場景2:當用戶點擊添加按鈕時,文本框內的數據應該被輸入到列表框內。一旦數據被輸入到列表框,它應該清空文本框的內容,并禁用添加和清除按鈕。

 設計模式問答2

場景2

場景3:- 當用戶點擊清除按鈕時,名字文本框內的內容被清空,并禁用添加和清除按鈕。

 設計模式問答2

場景3

現在從界面上來看上面幾個場景,我們可以推斷這些界面之間的交互是多么復雜。下圖“組件間復雜交互”顯示出了邏輯復雜性。

 設計模式問答2

組件間復雜交互

好了,讓我給你們看一個好看的圖,即下圖“通過調停者簡化”。與其組件之間直接通訊,不如通過一個作為調停者的中心組件通訊,調停者組件管理著發送給其他組件的消息,這樣邏輯更加優雅和清晰。

 設計模式問答2

通過調停者簡化

現在我們來看看代碼會是什么樣子。我們將使用C#,但是你可以很輕松的把這種思想應用在Java或其他語言上。下圖“調停者類”展示了一個調停者類完整的代碼概述。

調停者類做的第一件事,是保存擁有復雜通訊的類的引用。因此,我們 對外暴露了3個重載的方法“Register”。“Register”方法接收文本框對象和按鈕對象為參數。交互場景集中在 “ClickAddButton”,“TextChange”和“ClickClearButton”三個方法上。將根據場景不同,這些方法將管理UI組 件的可用與禁用。

 設計模式問答2

調停者類

現在的客戶邏輯非常優雅、非常酷。在構造函數中,我們首先將 參與復雜通訊的所有組件注冊到調停者對象中。然后在每個場景中,我們只需要調用調停者對象的函數。簡單地說,當有文本變化時,我們調用調停者對象的 “TextChange”函數;當用戶點擊添加按鈕時,我們調用“ClickAddButton”;當點擊清除按鈕時,調用 “ClickClearButton”函數。

 設計模式問答2

調停者模式的客戶邏輯

你能解釋備忘錄模式嗎?

備忘錄模式能夠在不破壞封裝原則的前提下,獲取對象內部狀態。備忘錄模式幫助我們存儲一個對象的快照,它可 以在任意時間被恢復。讓我們通過實例來理解。考慮圖“備忘錄示例”,它展示了一個顧客的界面。假設用戶開始編輯一條顧客記錄,并做了一些修改。然后用戶覺 得有錯誤,希望能夠恢復到原始的數據。這時備忘錄模式就登場了。它幫助我們存儲數據的一個備份,并且當用戶點擊“取消”按鈕時,對象能夠恢復到它的原始狀 態。

 設計模式問答2

備忘錄示例

讓我們嘗試用C#來實現剛才所講的顧客界面。下圖是顧客類 “clsCustomer”,它聚合了一個備忘錄類“clsCustomerMemento”。備忘錄類將保存數據的快照,它是顧客類 “clsCustomer”的精確的復制品(除了方法)。當顧客類“clsCustomer”初始化時,備忘錄類也將被初始化。當顧客類數據變化時,備忘 錄類的快照不變化。“Revert”函數把備忘錄的數據寫回到主類。

 設計模式問答2

顧客類的備忘錄

客戶端的代碼相當簡單。我們創建一個顧客類。一旦遇到問題,我們點擊“取消”按鈕,調用“Revert”函數,將修改過的數據恢復到備忘錄快照的原始數據。圖“備忘錄客戶端代碼”形象地展示了這個過程。

 設計模式問答2

備忘錄客戶端代碼

你能解釋觀察者模式嗎?

觀察者模式幫助我們與父類,關聯類或者依賴類之間進行通訊。觀察者模式中,有兩個重要的概念,分別是“主體”和“觀察者”。主體發 送通知,如果觀察者已經注冊到主體的話,觀察者會收到通知。下圖“主體和觀察者”展示了應用程序(主體)是如何給所有觀察者(郵件,事件日志,短消息服 務)發送通知的。你可以把這個例子對應到發布者與訂閱者模型。發布者就是應用程序,而訂閱者是郵件,事件日志和短消息服務。

 設計模式問答2

主體和觀察者

讓我們嘗試對前面定義的示例進行編碼。 首先我們看一下訂閱者/通知者類。圖“訂閱者類”做了一個直觀地展示。對所有的訂閱者,我們有一個公共的接口,“INotification”,它有一個 “notify”方法。所有需要接收通知的類,都需要實現這個“INotification”接口。所有需要接收通知的類,定義各自的響應方法。對當前場 景,我們只打印一個消息,表明特定的通知被執行了。

 設計模式問答2

訂閱者類

前面說過,觀察者模式中,有兩個部分,一個是我們前面說過的觀察者/訂閱者,另一個就是發布者,或者叫主體。

發布者有一個所有對接收通知感興趣的訂閱者的集合列表。通過“addNotification”和“removeNotification”,我們可以在列表中增加或者刪除訂閱者。“NotifyAll”方法遍歷所有的訂閱者,并發送通知。

 設計模式問答2

發布者類、主體類

現在,我們已經有了發布者和訂閱者類。我們來動手編寫一下客戶端代碼。下面是觀察者模式客戶端的代碼片段。首先我們創建一個擁有訂閱者集合的通知者對象。然后我們向集合中添加需要被通知的訂閱者。

現在,如果客戶端輸入的顧客代碼超過10個字符,就需要通知所有的訂閱者。

 設計模式問答2

觀察者模式客戶端代碼

如果你沒有學習過設計模式,或者不愿完全閱讀本文,請收看我們的免費視頻設計模式培訓和問答

許可

本文,以及相關的代碼和文件,通過 The Code Project Open License (CPOL) 協議授權。

原文鏈接: codeproject 翻譯: ImportNew.com - shenggordon
譯文鏈接: http://www.importnew.com/14347.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!