<設計模式:java語言中的應用>摘要、總結 收藏
<設計模式:java語言中的應用>一書已經學完,現做個摘要、總結。
創建模式(Creational Patterns)
Abstract Factory Builder
Factory Method Prototype
Singleton
結構模式(Structural Patterns)
Adapter Bridge
Composite Decorator
Facade Flyweight
Proxy
行為模式(Behavioral Pattern)
Chain of Responsibility Command
Interpreter Iterator
Mediator Memento
Observer State
Strategy Template Method
Visitor
一、創建模式(Creational Patterns)
1.Abstract Factory(抽象工廠)—把相關零件組合成產品
Abstract Factory Pattern 是把各種抽象零件組合成抽象產品。換句話說,處理的重點是在接口(API)而不是零件的具體實現。只利用接口(API)就能把零件組合成產品.
程序示例:
--Main.java 測試用的類
|-factory
| |-------Factory.java 表示抽象工廠的類(產生Link,Tray,Page)
| |-------Itme.java 用來統一處理Link和Tray的類
| |-------Link.java 抽象零件:表示HTML連接的類
| |-------Tray.java 抽象零件:抽取Link和Tray的類
| |-------Page.java 抽象零件:表示HTML網頁的類
|
|-listfactory
|-------listFactory.java 表示具體工廠的類(產生ListLink,ListTray,ListPage)
|-------listLink.java 具體零件:表示HTML連接的類
|-------listTray.java 具體零件:抽取Link和Tray的類
|-------listPage.java 具體零件:表示HTML網頁的類
步驟:定義抽象零件->用抽象零件定義抽象工廠->定義具體零件(繼承實現抽象零件)->定義具體工廠(繼承實現抽象工廠,制造實際產品)
2.Factory Method
Factory Method Pattern 在父類規定對象的創建方法,但并沒有深入到較具體的類名.所有具體的完整內容都放在子類.根據這個原則,我們可以大致分成產生對象實例的大綱(框架)和實際產生對象實例的類兩方面.
程序示例:
--Main.java 測試用的類
|-framework
| |-------Product.java 僅定義抽象方法use的抽象類
| |-------Factory.java 規定createProduct,registerProduct,實現create的抽象類(類似模板方法)
|
|-idcard
|-------IDCard.java 實現方法use的具體類
|-------IDCardFactory.java 實現方法createProduct,registerProduct的類
步驟:定義抽象產品->根據抽象產品定義抽象工廠->定義具體產品(繼承實現抽象產品)->定義具體工廠(繼承實現抽象工廠,制造實際產品)
3.Singleton(單件)-唯一的對象實例
Singleton Pattern 是針對一個類而言. Singleton類只會產生1個對象實例.Singleton類把singleton定義為static字段(類變量),再以Singleton類的對象實例進行初始化.這個初始化的操作僅在加載Singleton類時進行一次.
Singleton類的構造函數是private的,主要是為了禁止從非Singleton類調用構造函數.即使下面這個表達式不在此類之內,編譯時仍然會出現錯誤.
程序示例:
|--Main.java 測試用的類
|--Singleton.java 只有1個對象實例的類
步驟:定義一個該類類型的static字段,同時實例化->該類的構造方法設為private->定義一個static的getInstance()方法,返回已經實例化的static字段.
4.Builder(生成器)-組合復雜的對象實例
Builder Pattern 是采用循序漸進的方式組合較復雜對象實例的.
程序示例:
|--Main.java 測試用的類
|--Builder.java 規定建立文件時的方法的抽象類
|--Director.java 產生1個文件的類
|--TextBuilder.java 產生plaintext格式(一般文本格式)的類
|--HTMLBuilder.java 產生HTML格式的類
步驟:定義建立文件時的通用方法(Builder.java)->根據通用方法組織建立文件(Director.java)->根據不同需求實現建立文件的通用方法(TextBuilder.java,HTMLBuilder.java)
5.Prototype(原型)-復制建立對象
Prototype Pattern 不是利用類產生對象實例,而是從一個對象實例產生出另一個新對象實例.
程序示例:
|--Main.java 測試用的類
|--MessageBox.java 把字符串框起來use的類.實現use和createClone
|--UnderlinePen.java 把字符串加上下劃線的類.實現use和createCone
|--framework
|-------Product.java 已聲明抽象方法use和createClone的接口
|-------Manager.java 利用createClone復制對象實例的類
步驟:規定可復制產品的接口(Product.java,繼承Cloneable接口)->保存可復制的產品(以Product類型存以哈西表中),并提供復制產品的方法create(調用產品的復制方法,復制工作在具體產品類中執行)(Manager.java)->定義可復制的具體產品(UnderlinePen.java,MessageBox.java,實現復制產品方法)
二、結構模式(Structural Patterns)
1.Adapter(適配器)-換個包裝再度利用
Adapter Pattern 把既有的無法直接利用的內容轉換成必要的類型后再使用.具有填平"既有內容"和"需要結果"兩者間"落差"的功能.
Adapter Pattern 有繼承和委托兩種形式.
程序示例:
|--Main.java 測試用的類
|--Banner.java 具有原始功能showWithParen,showWithAster的類
|--Print.java 所需新功能printWeak,printStrong的接口或抽象類
|--PrintBanner.java 把原始功能轉換成新功能的類
步驟:
(繼承)構造具有原始功能的類(Banner.java)->定義具有新功能的接口(Print.java)->轉換(PrintBanner.java,繼承Banner實現Print接口,即繼承舊方法實現新功能)
(委托)構造具有原始功能的類(Banner.java)->定義具有新功能的抽象類(Print.java)->轉換(PrintBanner.java,繼承具有新功能的Print類.定義委托對象,即原始功能類.構造時傳入原始功能實例對象,新功能的實現利用委托對象的原始功能.)
2.Bridge(橋接)-分成功能層次和實現層次
Bridge Pattern 溝通著"功能的類層次"和"實現的類層次"
功能的類層次:給父類增加不同的功能
實現的類層次:給父類以不同的實現
Bridge Pattern 本質上是通過功能類(最上層的功能類)中的一個實現類(最上層的實現類,一般是抽象類)字段來橋接兩個類層次的.
程序示例:
|--Main.java 測試用的類
|--Display.java 功能類層次的最上層類
|--CountDisplay.java 功能類層次的新增功能類
|--DisplayImpl.java 實現類層次的最上層類
|--StringDisplayImpl.java 實現類層次的實現類
步驟:定義實現類層次的最上層類(DisplayImpl.java)->定義功能類層次的最上層類(Display.java,使用Adapter Pattern的委托方式把DisplayImpl.java的原始功能轉換成Display.java的新功能)->定義功能類層次的新增功能類(CountDisplay.java)->定義實現類層次的實現類(StringDisplayImpl.java)
3.Composite(組成)-對容器和內容一視同仁
有時候把容器和內容當作是同類來處理會比較好下手。容器里面可以是內容,也可以是更小一號的容器;而這個小一號的容器里還可以再放更小一號的容器,可以建立出像這樣大套小的結構和遞歸結構的Pattern就是Composite Pattern
使用Composite Pattern,容器和內容必須有一定的共性.
程序示例:
|--Main.java 測試用的類
|--File.java 表示文件的類
|--Directory.java 表示目錄的類
|--Entry.java 對File和Directory一視同仁的抽象類
|--FileTreatmentException.java 欲在文件內新增Entry時所發生的異常類
步驟:定義異常類(FileTreatmentException.java)->定義進入點類,即將容器和內容一視同仁的抽象類(Entry.java,容器和內容都含有共同的方法)->定義容器類和內容類(File.java,Directory.java,繼承Entry,實現通用方法)
4.Decorator(裝飾)-對裝飾和內容一視同仁
先建立一個核心對象,再一層層加上裝飾用的功能,就可以完成符合所需的對象.可以看成是多個通用的適配器.
程序示例:
|--Main.java 測試用的類
|--Display.java 打印字符串用的抽象類
|--StringDisplay.java 只有1行的打印字符串用的類
|--Border.java 表示"裝飾外框"的抽象類
|--SideBorder.java 只在左右加上裝飾外框的類
|--FullBorder.java 在上下左右加上裝飾外框的類
步驟:定義核心對象的抽象類(Display.java)->定義核心對象類(StringDisplay.java)->定義裝飾類的抽象類(Border.java,繼承核心對象的抽象類Display.java,以便裝飾和內容一視同仁.裝飾類中繼承自核心對象抽象類的方法委托給傳入的核心對象)->定義其它裝飾類(SideBorder.java,FullBorder.java,繼承Border.java)
5.Facade(外觀)-單一窗口
Facade Pattern 能整理錯綜復雜的來龍去脈,提供較高級的接口(API).Facade參與者讓系統外部看到較簡單的接口(API).而且Facade參與者還會兼顧系統內部各類功能和互動關系,以最正確的順序利用類.
Facade Pattern 把業務邏輯封裝起來,只提供一個簡單的接口給外部調用.
程序示例:
|--Main.java 測試用的類
|--maildata.txt 郵件列表文件
|--pagemaker
|-------Database.java 從郵件信箱取得用戶名稱的類
|-------HtmlWriter.java 產生HTML文件的類
|-------PageMaker.java 根據郵件信箱產生用戶網頁的類
步驟:定義業務邏輯需要的相關類(Database.java,HtmlWriter.java)->定義外部接口類(PageMaker.java)
6.Flyweight(享元)-有相同的部分就共享,采用精簡政策
"盡量共享對象實例,不做無謂的new".不是一需要對象實例就馬上new,如果可以利用其他現有的對象實例,就讓它們共享.這就是Flyweigth Pattern的核心概念.
Flyweight Pattern 實質是把創建的占用內存量大的對象存儲起來(一般用hashtable存儲),后續使用時,再從hashtable取出.
程序示例:
|--Main.java 測試用的類
|--BigChar.java 表示"大型字符"的類
|--BigCharFactory.java 共享并產生BigChar的對象實例的類
|--BigString.java 表示多個BigChar所產生的"大型文本"的類
步驟:定義占用內存量大,需要共享的類(Display.java)->定義共享實例的類(BigCharFactory.java,共享處理在此進行,將產生的共享對象存儲在哈希表中,第二次使用時從表中取出即可,不需要new)->定義共享對象組合使用類(BigString.java)
7.Proxy(代理)-需要再建立
代理就是那個代替本來應該自己動手做事的本人的人.
由于代理純粹只是代理工作而已,因此能力范圍也有限.如果遇到超出代理能力所及的范圍,代理就應該去找本人商量才對.
程序示例:
|--Main.java 測試用的類
|--Printer.java 表示命名的打印機的類(本人)
|--Printable.java Printer和PrinterProxy共享的接口
|--PrinterProxy.java 表示命名的打印機的類(代理)
步驟:定義本人和代理都能處理的問題的接口(Printable.java)->建立本人類(Printer.java,實現Printable.java接口)->建立代理類(PrinterProxy.java,定義本人字段,把代理無法處理的問題交給本人)
三、行為模式(Behavioral Pattern)
1.Chain of Responsibility(職責鏈)-責任轉送
先對人產生一個要求,如果這個人有處理的能力就處理掉;如果不能處理的話,就把要求轉送給"第二個人".同樣的,如果第二個人有處理的能力時就處理掉,不能處理的話,就繼續轉送給"第三個人",依此類推.這就是Chain of Responsiblility Pattern.
Chain of Responsibility Pattern 的關鍵在于定義轉送字段(next)和定義職責鏈.
程序示例:
|--Main.java 建立Support的連鎖,產生問題的測試用類
|--Trouble.java 表示發生問題的類.內有問題編號.
|--Support.java 解決問題的抽象類.內有轉送字段和處理方法.
|--NoSupport.java 解決問題的具體類(永遠"不處理")
|--LimitSupport.java 解決問題的具體類(解決小于指定號碼的問題)
|--OddSupport.java 解決問題的具體類(解決奇數號碼的問題)
|--SpecialSupport.java 解決問題的具體類(解決特殊號碼的問題)
步驟:建立問題類(Trouble.java)->建立解決問題的抽象類(Support.java,定義了轉送字段next,設置轉送字段的方法setNext和處理問題的方法support)->建立解決問題的具體類(NoSupport.java,LimitSupport.java,OddSupport.java,SpecialSupport.java,繼承Support.java)->產生處理問題的對象,建立職責鏈
2.Command(命令)-將命令寫成類
用一個"表示命令的類的對象實例"來代表欲執行的操作,而不需采用"調用方法"的類的動態處理.如欲管理相關紀錄,只需管理該對象實例的集合即可.而若預先將命令的集合存儲起來,還可再執行同一命令;或者是把多個命令結合成一個新命令供再利用.
Command Pattern 重點在于存儲/使用命令
程序示例:
--Main.java 測試用的類
|-command
| |-------Command.java 表示"命令"的接口
| |-------MacroCommand.java 表示"結合多個命名的命令"的類
|
|-drawer
|-------DrawCommand.java 表示"點的繪制命令"的類
|-------Drawable.java 表示"繪制對象"的接口
|-------DrawCanvas.java 表示"繪制對象"的類
步驟:建立命令接口(Command.java)->建立命令結合類(MacroCommand.java,將各個命令存儲到一個Stack類型的字段)->建立繪制命令類(DrawCommand.java,定義繪制對象字段drawable,實現命令接口)->建立繪制對象接口(Drawable.java)->建立繪制對象類(DrawCanvas.java,實現繪制對象接口,定義命令集合字段history)->測試
3.Interpreter(解釋器)-以類來表達語法規則
Interpreter Pattern 是用簡單的"迷你語言"來表現程序要解決的問題,以迷你語言寫成"迷你程序"而表現具體的問題.迷你程序本身無法獨自啟動,必須先用java語言另外寫一個負責"解釋(interpreter)"的程序.解釋程序能分析迷你語言,并解釋\執行迷你程序.這個解釋程序也稱為解釋器.當應解決的問題發生變化時,要修改迷你程序來對應處理.而不是修改用java語言寫成的程序.
迷你語言語法:
<program>::=program<command list>
<command list>::=<command>* end
<command>::=<repeat command>|<primitive command>
<repeat command>::=repeat<number><command list>
<primitive command>::=go|right|left
程序示例:
|--Main.java 測試用的類
|--Node.java 樹狀剖析中"節點"的類
|--ProgramNode.java 對應<program>的類
|--CommandListNode.java 對應<command list>的類
|--CommandNode.java 對應<command>的類
|--RepeatCommandNode.java 對應<repeat command>的類
|--PrimitiveCommandNode.java 對應<primitive command>的類
|--Context.java 表示語法解析之前后關系的類
|--ParseException.java 語法解析中的例外類
步驟:確定迷你語言的語法->建立語法解析類(Context.java,使用java.util.StringTokenizer類)->建立解析異常類(ParseException.java)->建立語法節點抽象類(Node.java,定義parse解析方法)->建立各語法節點對應的語法類(ProgramNode.java,CommandListNode.java,CommandNode.java,RepeatCommandNode.java,PrimitiveCommand.java,繼承語法節點Node.java類)
4.Iterator-迭代器
Iterator Pattern 是指依序遍歷并處理多個數字或變量.
程序示例:
|--Main.java 測試用的類
|--Aggregate.java 表示已聚合的類
|--Iterator.java 執行遞增\遍歷的接口
|--Book.java 表示書籍的類
|--BookShelf.java 表示書架的類
|--BookShelfIterator.java 掃描書架的類
步驟:定義聚合接口(Aggregate.java)->定義遍歷接口(Iterator.java)->建立具體的遍歷對象類(Book.java)->建立具體的聚合類(BookShelf.java,實現聚合接口)->建立具體的遍歷類(BookShelfIterator.java,實現遍歷接口)
5.Mediator(中介者)-只要面對一個顧問
每個成員都只對顧問提出報告,也只有顧問會發出指示給各個成員;成員們彼此也不會去探問目前狀況如何,或亂發指示給其他成員.
程序示例:
|--Main.java 測試用的類
|--Mediator.java 決定"顧問"接口(API)的接口
|--Colleague.java 決定"成員"接口(API)的接口
|--ColleagueButton.java 實現Colleagues接口.表示按鍵的類
|--ColleagueTextField.java 實現Colleagues接口.輸入文本的類
|--ColleagueCheckbox.java 實現Colleagues接口.表示選擇項目(在此為選擇按鈕)的類
|--LoginFrame.java 實現Mediator接口.表示登錄對話框的類
步驟:定義顧問接口(Mediator.java)->定義成員接口(Colleague.java)->建立具體的成員類(ColleagueButton.java,ColleagueTextField.java,ColleagueCheckbox.java,實現成員接口)->建立具體的顧問類(LoginFrame.java,實現顧問接口)
6.Memento(備忘錄)-存儲狀態
Memento Pattern 會把某個時間點的對象實例狀態記錄存儲起來,等到以后再讓對象實例復原到當時的狀態.
程序示例:
|--Main.java 進行游戲的類.先把Memento的對象實例存儲起來,如有必要時再復原Gamer的狀態
|--game
|-------Gamer.java 玩游戲的主人翁的類
|-------Memento.java 表示Gamer狀態的類.產生Memento的對象實例
步驟:建立需要存儲狀態的類(Gamer.java)->建立狀態類(Memento.java,狀態類與需要存儲狀態的類Gamer.java應具有相同的必要字段)
7.Observer(觀察者)-通知狀態變化
當被Observer Pattern 列入觀察名單的狀態發生變化,就會通知觀察者.在寫一些跟狀態變化有關的處理時,Observer Pattern是很好用的工具.
程序示例:
|--Main.java 測試用的類
|--Observer.java 表示觀察者的接口
|--NumberGenerator.java 表示產生數值對象的抽象類
|--RandomNumberGenerator.java 產生隨機數的類
|--DigitObserver.java 以數字表示數值的類
|--GraphObserver.java 以簡易長條圖表示數值的類
步驟:定義觀察者接口(Observer.java)->建立被觀察的類(NumberGenerator.java,RandomNumberGenerator.java,定義觀察者結合字段將觀察者存儲起來)->建立具體的觀察者類(DigitObserver.java,GraphObserver.java,實現觀察者接口)
8.State(狀態)-以類表示狀態
以類來表示狀態之后,只要切換類就能表現“狀態變化”,而且在必須新增其他狀態時,也很清楚該編寫哪個部分。
程序示例:
|--Main.java 測試用的類
|--State.java 表示金庫狀態的接口
|--DayState.java 實現State的類。表示白天的狀態
|--NightState.java 實現State的類。表示夜間的狀態
|--Context.java 管理金庫的狀態變化,跟保安中心聯絡的接口
|--SafeFrame.java 實現Context的類。含有按鈕、畫面顯示等的用戶接口
步驟:定義狀態接口(State.java,將使用State Pattern之前各種行為方法抽象出來)->建立具體的狀態類(DayState.java,NightState.java,實現狀態接口,狀態變化的具體動作在這里執行)->定義管理狀態變化的接口(Context.java,規定狀態變化及相關的調用方法)->建立狀態管理類(SafeFrame.java,實現狀態管理接口)
9.Strategy(策略)-把算法整個換掉
在Strategy Pattern之下,可以更換實現算法的部分而且不留痕跡。切換整個算法,簡化改為采用其他方法來解決同樣的問題。
程序示例:
|--Main.java 測試用的類
|--Hand.java 表示猜拳“手勢”的類
|--Strategy.java 表示猜拳“戰略”的接口
|--WinningStrategy.java 表示猜贏之后繼續出同樣招式的戰略的類
|--ProbStrategy.java 表示從上一次出的招式,以概率分配方式求出下一個招式機率的類
|--Player.java 表示玩猜拳的游戲者的類
步驟:定義策略接口(Strategy.java)->建立具體的策略類(WinningStrategy.java,ProbStrategy.java,實現策略接口)->建立使用策略的類(Player.java,定義策略字段,以便使用切換策略)->建立其它類(Main.java,Hand.java)
10.Template Method(模板方法)-實際處理交給子類
在父類指定處理大綱、在子類規定具體內容的Design Pattern就稱為Template Method Pattern
程序示例:
|--Main.java 測試用的類
|--AbstractDisplay.java 只實現方法display的抽象類
|--CharDisplay.java 實現方法open,print,close的類
|--StringDisplay.java 實現方法open,print,close的類
步驟:定義模板類(AbstractDisplay.java,實現dispaly方法,即制作了模板)->建立具體內容類(CharDisplay.java,StringDisplay.java,繼承模板類,實現模板類沒有實現的方法)
11.Visitor(訪問者)-在結構中穿梭還同時做事
Visitor Pattern 把數據結構和處理兩者分開,另外寫一個表示在數據結構內穿梭來去的主體“訪客”的類,然后把處理交給這個類來進行。如此一來,如果想追加新的處理行為時,只要再建立一個新的“訪客”即可。而在數據結構這邊,也只要能接受來敲門的“訪客”就能完成動作。
在父類指定處理大綱、在子類規定具體內容的Design Pattern就稱為Template Method Pattern
程序示例:
|--Main.java 測試用的類
|--Visitor.java 表示訪問文件或目錄的訪客的抽象類
|--Acceptor.java 表示接受Visitor類的對象實例的數據結構的接口
|--ListVisitor.java Visitor類的子類,打印文件和目錄信息的類
|--Entry.java File和Directory的父類的抽象類(實現Acceptor接口)
|--File.java 表示文件的類
|--Directory.java 表示目錄的類
|--FileTreatmentException.java 發生在對File進行add時的例外類
步驟:定義訪問者的抽象類(Visitor.java,定義訪問方法)->定義受訪者接口(Acceptor.java,定義接受訪問的方法)->建立具體的訪問者類(ListVisitor.java,繼承訪問者抽象類,實現訪問方法)->建立具體的受訪者類(Entry.java,File.java,Directory.java,實現受訪者接口)->編寫異常類(FileTreatmentException.java)
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/pian_yun/archive/2007/09/14/1784981.aspx