某知名IT企業筆試題: 程式設計:貓大叫一聲,所有的老鼠都開始逃跑,主人被驚醒。要求:(1) 要有聯動性,老鼠和主人的行為是被動的;(2) 考慮可擴充性,貓的叫聲可能引起其他聯動效應。 參考解答:【個人觀點】 本題可使用觀察者模式,參考類圖如下所示: 參考代碼如下: import java.util.*;interface Subject //抽象主題{ public void addObserver(Observer obs);
20.3 完整解決方案 為了協調介面組件對象之間的複雜互動關係,Sunny公司開發人員使用中介者模式來設計客戶資訊管理視窗,其結構20-7所示:圖20-7 引入了中介者類的“客戶資訊管理視窗”結構 圖20-7隻是一個重構之後的結構,在具體實現時,為了確保系統具有更好的靈活性和可擴充性,我們需要定義抽象中介者和抽象組件類,其中抽象組件類是所有具體組件類的公用父類,完整類圖20-8所示:圖20-8 重構後的“客戶資訊管理視窗”結構圖
20.4 中介者與同事類的擴充 Sunny軟體公司CRM系統的客戶對“客戶資訊管理視窗”提出了一個修改意見:要求在視窗的下端能夠及時顯示當前系統中客戶資訊的總數。修改之後的介面20-9所示:圖20-9 修改之後的“客戶資訊管理視窗”介面圖 從圖20-9中我們不難發現,可以通過增加一個文字標籤(Label)來顯示客戶資訊總數,而且當使用者點擊“增加”按鈕或者“刪除”按鈕時,將改變文字標籤的內容。
3 完整解決方案 Sunny軟體公司開發人員使用狀態模式來解決賬戶狀態的轉換問題,用戶端只需要執行簡單的存款和取款操作,系統根據餘額將自動轉換到相應的狀態,其基本結構4所示:圖4 銀行賬戶結構圖 在圖4中,Account充當環境類角色,AccountState充當抽象狀態角色,NormalState、OverdraftState和RestrictedState充當具體狀態角色。完整代碼如下所示:溫馨提示:代碼有點長,需要有耐心!//銀行賬戶:環境類class
4 共用狀態 在有些情況下,多個環境對象可能需要共用同一個狀態,如果希望在系統中實現多個環境對象共用一個或多個狀態物件,那麼需要將這些狀態物件定義為環境類的靜態成員對象。 下面通過一個簡單一實例來說明如何?共用狀態: 如果某系統要求兩個開關對象要麼都處於開的狀態,要麼都處於關的狀態,在使用時它們的狀態必須保持一致,開關可以由開轉換到關,也可以由關轉換到開。 可以使用狀態模式來實現開關的設計,其結構5所示:圖5 開關及其狀態設計結構圖
2 狀態模式概述 狀態模式用於解決系統中複雜物件的狀態轉換以及不同狀態下行為的封裝問題。當系統中某個對象存在多個狀態,這些狀態之間可以進行轉換,而且對象在不同狀態下行為不相同時可以使用狀態模式。狀態模式將一個對象的狀態從該對象中分離出來,封裝到專門的狀態類中,使得對象狀態可以靈活變化,對於用戶端而言,無須關心對象狀態的轉換以及對象所處的目前狀態,無論對於何種狀態的對象,用戶端都可以一致處理。 狀態模式定義如下:狀態模式(State
20.2 中介者模式概述 如果在一個系統中對象之間的聯絡呈現為網狀結構,20-4所示。對象之間存在大量的多對多聯絡,將導致系統非常複雜,這些對象既會影響別的對象,也會被別的對象所影響,這些對象稱為同事對象,它們之間通過彼此的相互作用實現系統的行為。在網狀結構中,幾乎每個對象都需要與其他對象發生相互作用,而這種相互作用表現為一個對象與另外一個對象的直接耦合,這將導致一個過度耦合的系統。圖20-4 對象之間存在複雜關係的網狀結構
5 使用環境類實現狀態轉換 在狀態模式中實現狀態轉換時,具體狀態類可通過調用環境類Context的setState()方法進行狀態的轉換操作,也可以統一由環境類Context來實現狀態的轉換。此時,增加新的具體狀態類可能需要修改其他具體狀態類或者環境類的原始碼,否則系統無法轉換到新增狀態。但是對於用戶端來說,無須關心狀態類,可以為環境類設定預設的狀態類,而將狀態的轉換工作交給具體狀態類或環境類來完成,具體的轉換細節對於用戶端而言是透明的。
4 鉤子方法的使用 模板方法模式中,在父類中提供了一個定義演算法架構的模板方法,還提供了一系列抽象方法、具體方法和鉤子方法,其中鉤子方法的引入使得子類可以控制父類的行為。最簡單的鉤子方法就是空方法,代碼如下:public virtual void Display() { } 當然也可以在鉤子方法中定義一個預設的實現,如果子類不覆蓋鉤子方法,則執行父類的預設實現代碼。
接文章《如何在類圖中標註設計模式(一)》。本文姍姍來遲,見諒! 5. 基於標記的模式標註 美國德克薩斯大學達拉斯分校的Jing Dong等人提出了一種基於標記的模式標註方法(Tagged Pattern Notation)。該方法通過向原有結構圖中附加標記值(Tagged
11.3 完整解決方案 為了讓系統具有更好的靈活性和可擴充性,用戶端可以一致地對待檔案和檔案夾,Sunny公司開發人員使用組合模式來進行殺毒軟體的架構設計,其基本結構11-5所示:圖11-5 殺毒軟體架構設計結構圖 在圖11-5中, AbstractFile充當抽象構件類,Folder充當容器構件類,ImageFile、TextFile和VideoFile充當葉子構件類。完整代碼如下所示:import java.util.*;//抽象檔案類:抽象構件abstract
11.4 透明組合模式與安全性群組合模式 通過引入組合模式,Sunny公司設計的殺毒軟體具有良好的可擴充性,在增加新的檔案類型時,無須修改現有類庫代碼,只需增加一個新的檔案類作為AbstractFile類的子類即可,但是由於在AbstractFile中聲明了大量用於管理和訪問成員構件的方法,例如add()、remove()等方法,我們不得不在新增的檔案類中實現這些方法,提供對應的錯誤提示和異常處理。為了簡化代碼,我們有以下兩個解決方案: 解決方案一:將葉子構件的add()、
面板模式是一種使用頻率非常高的結構型設計模式,它通過引入一個外觀角色來簡化用戶端與子系統之間的互動,為複雜的子系統調用提供一個統一的入口,降低子系統與用戶端的耦合度,且用戶端調用非常方便。 1. 面板模式概述
11.5 公司組織圖 在學習和使用組合模式時,Sunny軟體公司開發人員發現樹形結構其實隨處可見,例如Sunny公司的組織圖就是“一棵標準的樹”,11-8所示:圖11-8 Sunny公司組織圖 在Sunny軟體公司的內部辦公系統Sunny
3. 面板模式應用執行個體 下面通過一個應用執行個體來進一步學習和理解面板模式。 1. 執行個體說明
4. 抽象外觀類 在標準的面板模式結構圖中,如果需要增加、刪除或更換與外觀類互動的子系統類,必須修改外觀類或用戶端的原始碼,這將違背開閉原則,因此可以通過引入抽象外觀類來對系統進行改進,在一定程度上可以解決該問題。在引入抽象外觀類之後,用戶端可以針對抽象外觀類進行編程,對於新的業務需求,不需要修改原有外觀類,而對應增加一個新的具體外觀類,由新的具體外觀類來關聯新的子系統對象,同時通過修改設定檔來達到不修改任何原始碼並更換外觀類的目的。
為了方便大家更加系統地學習和掌握各種常用的設計模式,下面通過一個綜合執行個體——“多人聯機射擊遊戲”來學習如何在實際開發中綜合使用設計模式。 反恐精英(Counter-Strike, CS)、三角洲部隊、戰地等多人聯機射擊遊戲廣受玩家歡迎,在多人聯機射擊遊戲的設計中,可以使用多種設計模式。下面我選取一些較為常用的設計模式進行分析: (1) 抽象原廠模式
(6) 觀察者模式
1. 模板方法模式概述 在現實生活中,很多事情都包含幾個實現步驟,例如請客吃飯,無論吃什麼,一般都包含點單、吃東西、買單等幾個步驟,通常情況下這幾個步驟的次序是:點單 --> 吃東西 --> 買單。在這三個步驟中,點單和買單大同小異,最大的區別在於第二步——吃什嗎?吃麵條和吃滿漢全席可大不相同,1所示:圖1 請客吃飯
3 模板方法模式應用執行個體 下面通過一個應用執行個體來進一步學習和理解模板方法模式。 1. 執行個體說明 某軟體公司欲為某銀行的業務支撐系統開發一個利息計算模組,利息計算流程如下: (1) 系統根據帳號和密碼驗證使用者資訊,如果使用者資訊錯誤,系統顯示出錯提示; (2) 如果使用者資訊正確,則根據使用者類型的不同使用不同的利息計算公式計算利息(如活期賬戶和定期賬戶具有不同的利息計算公式); (3) 系統顯示利息。