版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第6章行為模式(一)本章目標了解什么是命令模式>掌握命令模式的應用了解什么是觀察者模式>掌握觀察者模式的應用本章單詞:action invokeraction invoker observer transaction receiver 6.1命令模式(Command)6.1.1概念1、名稱命令(Command)模式屬于對象的行為模式【GOF95】。命令模式又稱為行動(Action)模式或交易(Transaction)模式。命令模式把一個請求或者操作封裝到一個對象中。命令模式允許系統(tǒng)使用不同的請求把客戶端參數(shù)化,對請求排隊或者記錄請求日志,可以提供命令的撤銷和恢復功能。命令模式是對命令的封裝。命令模式把發(fā)出命令的責任和執(zhí)行命令的責任分割開,委派給不同的對象。每一個命令都是一個操作:請求的一方發(fā)出請求要求執(zhí)行一個操作;接收的一方收到請求,并執(zhí)行操作。命令模式允許請求的一方和接收的一方獨立開來,使得請求的一方不必知道接收請求的一方的接口,更不必知道請求是怎么被接收,以及操作是否被執(zhí)行、何時被執(zhí)行,以及是怎么被執(zhí)行的。2、結構命令模式不是新的發(fā)明,在美猴王大鬧天宮之前就有了。那時玉帝命令太白金星召美猴王上天:"金星徑入(水簾洞)當中,面南立定道:'我是西方太白金星,奉玉帝招安圣旨,下界請你上大,拜受仙錄。'"玉帝是系統(tǒng)的客戶端,太白金星是命令的發(fā)出者,猴王是命令的接收者,圣旨就是命令。玉帝的這一道命令就是要求猴王到上界報到。玉帝只管發(fā)出命令,而不管命令是怎樣傳達到美猴王的。太白金星負責將圣旨傳到,可是美猴王怎么執(zhí)行圣旨、何時執(zhí)行圣旨是美猴王自己的事。果不然,個久美猴王就大鬧了天宮。這個模擬系統(tǒng)的設計如圖6-1所示。OA執(zhí)行0:四訶執(zhí)行QOA執(zhí)行0:四訶執(zhí)行Q:widclassCommand玉皇大誥盤白金星圖6-1模擬結構命令模式的類圖如圖6-2所示。3、意圖將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數(shù)化;對請求排隊或記錄請求日志,以及支持可取消的操作。這里所謂的“不同的請求”也既意味著請求可能發(fā)生的變化,是一個可能擴展的功能點。4、適用性抽象出待執(zhí)行的動作以參數(shù)化某對象,適用過程語言中的回調函數(shù)表達這種參數(shù)化的機制。所謂的回調函數(shù)指函數(shù)先在某處注冊,而他將在稍后的某個需要的時候被調用。Command模式是回調機制的一個面向對象的替代品。+在不同的時刻指定、排列和執(zhí)行的請求。支持取消操作。支持修改日志,這樣當系統(tǒng)崩潰時這些修改可以被從新作一遍。用構建在原語操作上的高層操作構造一個系統(tǒng)。這樣一種結構支持事務的信息系統(tǒng)中很常見。5、個角色+客戶(Client)角色:創(chuàng)建了一個具體命令(ConcreteCommand)對象并確定其接收者。+命令(Command)角色:聲明了一個給所有具體命令類的抽象接口。這是一個抽象角色。+具體命令(ConcreteCommand)角色:定義一個接受者和行為之間的弱耦合;實現(xiàn)Execute()方法,負責調用接收考的相應操作。Execute()方法通常叫做執(zhí)方法。請求者(Invoker)角色:負責調用命令對象執(zhí)行請求,相關的方法叫做行動方法。接收者(Receiver)角色:負責具體實施和執(zhí)行一個請求。任何一個類都可以成為接收者,實施和執(zhí)行請求的方法叫做行動方法。6.1.2作用有時必須向一個對象提交請求,但是并不知道關于被請求的操作或者請求的接受者的任何信息。命令模式通過將請求本身變成一個對象來使工具箱對象可向未指定的應用對象提出請求,這個對象可以被存儲并像其他的對象一樣被傳遞,這一個模式的關鍵是抽象的Command類,它定義了一個執(zhí)行操作的接口,其最簡單的形式是一個抽象的Execute操作,具體的Command子類將接收者作為其一個實例變量,并實現(xiàn)Execute操作,制定接收者采取的動作,而接收者有執(zhí)行該請求所需的具體信息。6.1.3適用范圍在下面的情況下應當考慮使用命令模式:+使用命令模式作為“CallBack”在面向對象系統(tǒng)中的替代。“CallBack”講的便是先將一個函數(shù)登記上,然后在以后調用此函數(shù)。需要在不同的時間指定請求、將請求排隊。一個命令對象和原先的請求發(fā)出者可以有不同的生命期。換言之,原先的請求發(fā)出者可能已經不在了,而命令對象本身仍然是活動的。這時命令的接收者可以是在本地,也可以在網絡的另外一個地址。命令對象可以在串形化之后傳送到另外一臺機器上去。+系統(tǒng)需要支持命令的撤消(undo)。命令對象可以把狀態(tài)存儲起來,等到客戶端需要撤銷命令所產生的效果時,可以調用undo()方法,把命令所產生的效果撤銷掉。命令對象還可以提供redo()方法,以供客戶端在需要時,再重新實施命令效果。如果一個系統(tǒng)要將系統(tǒng)中所有的數(shù)據更新到日志里,以便在系統(tǒng)崩潰時,可以根據日志里讀回所有的數(shù)據更新命令,重新調用Execute()方法一條一條執(zhí)行這些命令,從而恢復系統(tǒng)在崩潰前所做的數(shù)據更新。+一個系統(tǒng)需要支持交易(Transaction)。一個交易結構封裝了一組數(shù)據更新命令。使用命令模式來實現(xiàn)交易結構可以使系統(tǒng)增加新的交易類型。6.1.4實現(xiàn)下面是一個簡單命令模式的實現(xiàn)代碼。接收者角色:*接收者類@authorsanlian@versionNov25,20104:34:52PM*/publicclassReceiver{/***請求一*/publicvoidactionOne(){System.ou亡.println("ActionOnehasbeentaken.");}/***請求二*/publicvoidactionTwo(){System.ou亡.println("ActionTwohasbeentaken.");}}命令角色:/***命令接口@authorsanlian@versionNov25,20104:21:15PM*/publicinterfaceCommand{/***執(zhí)行方法*/voidexecute();}/***具體命令實現(xiàn)一@authorsanlian@versionNov25,20104:34:30PM*/publicclassConcreteCommandOneimplementsCommand{privateReceiverreceiver;publicConcreteCommandOne(Receiverrec){thisreceiver=rec;}publicvoidexecute() {receiver.actionOne();}}/***具體命令實現(xiàn)二@authorsanlian@versionNov25,20104:37:12PM*/publicclassConcreteCommandTwoimplementsCommand{privateReceiverreceiver;publicConcreteCommandTwo(Receiverrec){thisreceiver=rec;}publicvoidexecute() {this.receiver.actionTwo();}}調用者角色:/***調用者@authorsanlian@versionNov25,20104:37:35PM*/publicclassInvoker{privateCommandcmdOne;privateCommandcmdTwo;publicInvoker(Commandone,Commandtwo){this.cmdOne=one;this.cmdTwo=two;}publicvoidactionOne(){this.cmdOne.execute();}publicvoidactionTwo(){this.cmdTwo.execute();}}客戶端角色:packagemand;/***客戶端@authorsanlian@versionNov25,20104:42:26PM*/publicclassClient{publicstaticvoidmain(String[]args){Receiverrec=newReceiver();Commandone=newConcreteCommandOne(rec);Commandtwo=newConcreteCommandTwo(rec);Invokerink=newInvoker(one,two);ink.actionOne();ink.actionTwo();}}執(zhí)行結果如圖6-3所示。圖6-3運行結果上面的代碼似乎顯的很多余,本來可以使用更簡單的實現(xiàn),代碼如下:publicclassReceiver{publicvoidactionOne(){System.ou亡.println("ActionOnehasbeentaken.");}publicvoidactionTwo(){System.ou亡.println("ActionTwohasbeentaken.");}}publicclassClient{publicstaticvoidmain(String[]args){Receiverrec=newReceiver();rec.actionOne();rec.actionTwo();}J看多簡潔,如果是像上邊如此簡單的需求,這個才應該是我們的選擇,但是有些情況下這樣的寫法不能解決的,或者說解決起來不好,所以引入命令模式。如以下情況:+我們須要Client和Receiver同時開發(fā),而且在開發(fā)過程中分別須要不停重購,改名。+如果我們要求Redo,Undo等功能。我們須要命令不按照調用執(zhí)行,而是按照執(zhí)行時的情況排序,執(zhí)行。開發(fā)后期,我們發(fā)現(xiàn)必須要log哪些方法執(zhí)行了,如何在盡量少更改代碼的情況下實現(xiàn),并且漸少重復代碼。在上邊的情況下,我們的接受者有很多,不止一個。解決辦法:+情況一:我們可以定義一個接口,讓Receiver實現(xiàn)這個接口‘Client按照接口調用。+情況二:我們可以讓Receiver記住一些狀態(tài),例如執(zhí)行前的自己的狀態(tài),用來undo,但自己記錄自己的狀態(tài)實現(xiàn)起來比較混亂,一般都是一個累記錄另一個類的狀態(tài)。情況三:很難實現(xiàn)。+情況四:我們須要在每個Action,前后加上log+情況五:相對好實現(xiàn),但是再加上這個,是否感覺最終的實現(xiàn)很混亂呢好,我們再來看看命令模式,在命令模式中,我們增加一些過渡的類,這些類就是上邊的命名接口和命令實現(xiàn),這樣就很好的解決了情況一,情況二。我們再加入一個Invoker,這樣情況三和情況四就比較好解決了。如下加入Log和排序后的Invoker:packagemand;importjava.util.ArrayList;importjava.util.List;/***調用者@authorsanlian@versionNov25,20104:37:35PM*/publicclassInvoker{privateListcmdList=newArrayList();publicvoidadd(Commandcmd){this.cmdList.add(cmd);}publicvoidremove(Commandcmd){this.cmdList.remove(cmd);}publicvoidaction(){Commandcmd;while((cmd=getCmd())!=null){System.ou亡.println("log:begin"+cmd.getClass().getName());cmd.execute();System.ou亡.println("log:end"+cmd.getClass().getName());}}publicCommandgetCmd(){Commandcmd=null;//按照自定義優(yōu)先級,排序去除cmdreturncmd;}}客戶端代碼如下:packagemand;/***客戶端@authorsanlian@versionNov25,20104:42:26PM*/publicclassClient{publicstaticvoidmain(String[]args){Receiverrec=newReceiver();Command one = new ConcreteCommandOne(rec);Command two = new ConcreteCommandTwo(rec);Invoker ink = new Invoker();ink.add(one);ink.add(two);ink.action();}}該實例的最終結構如圖6-4所示。圖6-4結構圖6.1.5優(yōu)缺點1、優(yōu)點命令模式使新的命令很容易地被加入到系統(tǒng)里。+允許接收請求的一方決定是否要否決(Veto)請求。能較容易地設計-個命令隊列。+可以容易地實現(xiàn)對請求的Undo和Redo。+在需要的情況下,可以較容易地將命令記入日志。命令模式把請求一個操作的對象與知道怎么執(zhí)行一個操作的對象分割開。命令類與其他任何別的類一樣,可以修改和推廣。+你可以把命令對象聚合在一起,合成為合成命令。比如宏命令便是合成命令的例子。合成命令是合成模式的應用。由于加進新的具體命令類不影響其他的類,因此增加新的具體命令類很容易。2、缺點使用命令模式會導致某些系統(tǒng)有過多的具體命令類。某些系統(tǒng)可能需要幾十個,幾百個甚至幾千個具體命令類,這會使命令模式在這樣的系統(tǒng)里變得不實際。6.2觀察者模式(Observer)6.2.1概念1、名稱觀察者模式又叫做發(fā)布-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監(jiān)聽器(Source/Listener)模式或從屬者(Dependents)模式。觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監(jiān)聽某一個主題對象。這個主題對象在狀態(tài)上發(fā)生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。一個軟件系統(tǒng)常常要求在某一個對象的狀態(tài)發(fā)生變化的時候,某些其它的對象做出相應的改變。做到這一點的設計方案有很多,但是為了使系統(tǒng)能夠易于復用,應該選擇低耦合度的設計方案。減少對象之間的耦合有利于系統(tǒng)的復用,但是同時設計師需要使這些低耦合度的對象之間能夠維持行動的協(xié)調一致,保證高度的協(xié)作(Collaboration)。觀察者模式是滿足這一要求的各種設計方案中最重要的一種。2、結構觀察者模式的類圖如圖6-5所示。圖6-5觀察者模式結構3、意圖觀察者模式屬于行為型模式,其意圖是定義對象間的一種一對多的依賴關系,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。4、適用性在以下的任一情況下可以使用觀察者模式:+當一個抽象模型有兩個方面,其中一個方面依賴于另一方面。將這二者封裝在獨立的對象中可以使他們各自獨立地改變和復用。+當對一個對象的改變需要同時改變其它對象,而不知道具體由多少對象有待改變。當一個對象必須通知其他對象,而它又不能假定其他對象是誰,換言之,你不希望這些對象是緊密耦合的。5、角色觀察者模式的實現(xiàn)里有下面這些角色:+抽象主題(Subject)角色:主題角色把所有對觀察考對象的引用保存在一個聚集里,每個主題都可以有任何數(shù)量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象,主題角色又叫做抽象被觀察者(Observable)角色,一般用一個抽象類或者一個接口實現(xiàn)。+抽象觀察者(Observer)角色:為所有的具體觀察者定義一個接口,在得到主題的通知時更新自己。這個接口叫做更新接口。抽象觀察者角色一般用一個抽象類或者一個接口實現(xiàn)。在這個示意性的實現(xiàn)中,更新接口只包含一個方法(即Update()方法),這個方法叫做更新方法。+具體主題(ConcreteSubject)角色:將有關狀態(tài)存入具體現(xiàn)察者對象;在具體主題的內部狀態(tài)改變時,給所有登記過的觀察者發(fā)出通知。具體主題角色又叫做具體被觀察者角色(ConcreteObservable)。具體主題角色通常用一個具體子類實現(xiàn)。+具體觀察者(ConcreteObserver)角色:存儲與主題的狀態(tài)自恰的狀態(tài)。具體現(xiàn)察者角色實現(xiàn)抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題的狀態(tài)相協(xié)調。如果需要,具體現(xiàn)察者角色可以保存一個指向具體主題對象的引用。具體觀察者角色通常用一個具體子類實現(xiàn)。從具體主題角色指向抽象觀察者角色的合成關系,代表具體主題對象可以有任意多個對抽象觀察者對象的引用。之所以使用抽象觀察者而不是具體觀察者,意味著主題對象不需要知道引用了哪些ConcreteObserver類型,而只知道抽象Observer類型。這就使得具體主題對象可以動態(tài)地維護一系列的對觀察者對象的引用,并在需要的時候調用每一個觀察者共有的Update()方法。這種做法叫做“針對抽象編程”。6.2.2作用+屏蔽線程間的通信機制:例如兩個線程之間,主線程可以作為觀察者,執(zhí)行線程是被觀察者。彼此之間只知道對方存在,但不知道之間通信的細節(jié)。消除硬編碼:如果沒有Observer模式,則只能采用回調的模式,或者在代碼中顯示地調用觀察者。優(yōu)化異常機制:特別適合在異常發(fā)生時向頂層監(jiān)控,減少try-catch代碼量。6.2.3實現(xiàn)老師有電話號碼,學生需要知道老師的電話號碼以便于在合時的時候撥打,在這樣的組合中,老師就是一個被觀察者(Subject),學生就是需要知道信息的觀察者,當老師的電話號碼發(fā)生改變時,學生得到通知,并更新相應的電話記錄。整體的結構如圖6-6所示。圖6-6結構圖觀察者接口Observer代碼如下:packagecom.sanlian.mode.observer;/***觀察者@authorsanlian@versionNov26,201012:47:17PM*/被觀察者接口Subject代碼如下:packagecom.sanlian.mode.observer;/***被觀察者接口@authorsanlian@versionNov26,20101:08:38PM*/publicinterfaceSubject{publicvoidattach(Observero);publicvoiddetach(Observero);publicvoidnotice();}被觀察者實現(xiàn)類Teacher代碼如下:packagecom.sanlian.mode.observer;importjava.util.Vector;/***教師,被觀察者實現(xiàn)類@authorsanlian@versionNov26,20101:06:25PM*/publicclassTeacherimplementsSubject{privateStringphone; //電話privateVectorstudents;//觀者者集合publicTeacher(){phone="";students=newVector();}/***添加觀察者*/publicvoidattach(Observero){students.add(o);}/***移除觀察者*/publicvoiddetach(Observero){students.remove(o);}/***更新*/publicvoidnotice(){for(inti=0;i<students.size();i++){((Observer)students.get(i)).update();}}/***更改電話號碼*@paramphone*/publicvoidsetPhone(Stringphone){this.phone=phone;notice();}publicStringgetPhone(){returnphone;}}觀察者實現(xiàn)類Student代碼如下:packagecom.sanlian.mode.observer;/***學生類,具體觀察者@authorsanlian@versionNov26,201012:59:34PM*/publicclassStudentimplementsObserver{privateStringname;//姓名privateStringphone; //老師電話privateTeacherteacher;//老師publicStudent(Stringname,Teachert){=name;teacher=t;}/***顯示信息*/publicvoidshow(){System.out.println("Name:"+name+"\t老師電話:"+phone);}/***更新*/publicvoidupdate(){phone=teacher.getPhone();}}測試類Test代碼如下:packagecom.sanlian.mode.observer;importjava.util.Vector;/***客戶端、測試類@authorsanlian@versionNov26,20101:04:41PM*/publicclassTest{publicstaticvoidmain(String[]args){//被觀察者Teachert=newTeacher();//創(chuàng)建觀察者集合VectorstuList=newVector();for(inti=0;i<10;i++)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年東臺市市級機關公開轉任公務員備考題庫及1套參考答案詳解
- 2025年梓潼縣公開考核招聘衛(wèi)生專業(yè)技術人員26人備考題庫及答案詳解參考
- 2025年懷化市老齡協(xié)會招聘招募備考題庫有答案詳解
- 2025年崇州市人民醫(yī)院醫(yī)共體成員單位自主招聘(補充招聘)備考題庫及完整答案詳解1套
- 2025年湘潭市九華中學(長沙市一中九華中學)代課教師招聘備考題庫及完整答案詳解1套
- 福建省能源石化集團有限責任公司2025年秋季招聘備考題庫及參考答案詳解1套
- 湖南時空信息安全檢測服務有限公司2025年面向社會公開招聘備考題庫及一套參考答案詳解
- 簡約商務風年度工作總結匯報
- 2025年中國煤炭地質總局應屆高校畢業(yè)生招聘467人備考題庫及參考答案詳解一套
- 手繪水彩中國風二十四節(jié)氣立秋科普模板
- 泌尿系統(tǒng)疾病總論
- 勞動仲裁授課課件
- 新工廠工作匯報
- 山西低空經濟發(fā)展現(xiàn)狀
- 汽車電子工程師崗位面試問題及答案
- 錢乙完整版本
- HXN5型機車柴油機的結構特點柴油機84課件
- 高速公路維修施工方案與措施
- 紡織品的物理化學性質試題及答案
- 發(fā)改價格〔2007〕670號建設工程監(jiān)理與相關服務收費標準
- 高空作業(yè)吊板施工方案
評論
0/150
提交評論