Command: Yufeng Wu Reference: Gof Book Ch.5
Command: Yufeng Wu Reference: Gof Book Ch.5
1.Command
InaGUIapplication,clickmenu method requestsome
WhataboutcallingthemethoddirectlyintheMenuItem class?
BehavioralDesignPattern
Yufeng Wu Reference:GoF bookCh.5.
1
Commandpattern:turntherequesttoanobject
ExampleCode
publicinterfaceCommand { publicvoidExecute(); }; publicclassOpenCommand implements Command{ publicOpenCommand(Application) {_application=a; } publicvoidExecute(){ conststringname=AskUser(); If(name!=){ Documentdocument=new Document(name); _application.Add(document); document.Open();} } protectedconststringAskUser(){} private:Application_application; string_response; } publicclassPasteCommand implements Command{ publicPasteCommand(Document) {_document=doc} voidExecute(){_document.Paste();} privateDocument_document; };
Undoability
AddanUnexecute methodtoCommand interface. Commandhistory.
2.Iterator
Consideralistclass(aggregate).Needto accessmembers. UseIterator pattern.Whynotjustaddsome querymethodsintheListclass? query methods in the List class?
2/16/2012
Iterator
ExampleCode
publicclassList{ publicList(int size= DEFAULT_LIST_CAPACITY){} int Count()const{} ItemGet(int index)const{} }; publicinterfaceIterator { bl f { publicvoidFirst(); publicvoidNext(); publicbool IsDone()const; ItemCurrentItem()const; } publicclassListIterator implement Iterator{ publicListIterator(constList aList){ _list=aList; _current=0;} publicvoidFirst(){_current=0;} publicvoidNext(){_current++;} publicbool IsDone()const{ public bool IsDone() const{ return_current>=_list.Count();} publicItemCurrentItem()const{ if(IsDone()){ throwIteratorOutOfBounds; } return_list.Get(_current); } privateconstList_list; long_current; }; 8
Examples
voidPrintEmployees (Iterator i) { for(i.First();i.IsDone()==false; i.Next()) { i.CurrentItem().Print(); } } //use Listemployees; //... ListIterator forward(employees); ReverseListIterator backward(employees); PrintEmployees(forward); PrintEmployees(backward); //betterway:abstractlist publicinterfaceAbstractList { publicIterator CreateIterator(); }; //concretelist publicclassListimplements AbstractList { Iterator ListCreateIterator (){ returnnewListIterator(this); } } //weknowonlythatwehavean AbstractList employees;. Iterator iterator = employees.CreateIterator(); PrintEmployees(iterator); 9
3.Mediator
OO:distributionofbehavior Interconnectionofobjects:reducereusability Example:dependenceofitemsindialogbox.
10
Mediator
Mediator:controlandcoordinateagroupof objects.
Mediatorexample
Notetheuseofabstractinterface.
11
12
2/16/2012
Examplecode
publicinterfaceDialogDirector { publicvoidShowDialog(); publicvoid WidgetChanged(Widgetw); } publicabstractclassWidget{ publicWidget(DialogDirector d) {..} { } publicvoidChanged(){ _director.WidgetChanged(this); } publicvoid HandleMouse(MouseEvent event); //... privateDialogDirector _director; }; publicclassListBox extendsWidget{ publicListBox(DialogDirector){} publicstringGetSelection(){} publicvoidSetList(ListlistItems){} publicvoid HandleMouse(MouseEvent event){} //... }; }; publicclassEntryField extendsWidget{ publicEntryField(DialogDirector d){} publicvoidSetText(conststringtext) {} publicconststringGetText(){} pubicvoid HandleMouse(MouseEvent event){} //... };
13
Examplecode
publicclassButtonextendsWidget{ publicButton(DialogDirector){} publicvoidSetText(conststringtext){} publicvoidHandleMouse(MouseEvent event){ // Changed(); } //... // }; //Fontdialogbox publicclassFontDialogDirector implements DialogDirector { publicFontDialogDirector(){} protectedvoidCreateWidgets() { _ok=newButton(this); _cancel=newButton(this); _fontList =newListBox(this); _fontName =newEntryField(this); } publicvoidWidgetChanged(Widget theChangedWidget ) { if(theChangedWidget ==_fontList){ _fontName.SetText( _fontList.GetSelection());} elseif(theChangedWidget ==_ok){ //applyfontchangeanddismissdialog //... // }elseif(theChangedWidget ==_cancel) { //dismissdialog } } privateButton_ok; privateButton_cancel; ListBox _fontList; EntryField _fontName; };
14
4.Observer
Keepseveralobjectconsistent:publish subscribe
Modelviewcontrollerpattern Subject (document in example) Subject(documentinexample) Observer(viewinexample) Subjectnotifiesobserverchange,andobserver queriessubjectforupdate.
Observer
15
16
Examplecode
publicinterfaceObserver{ publicvoidUpdate(Subject theChangedSubject); }; publicabstractclassSubject{ publicvoidAttach(Observero){ _observers.Append(o) } publicvoidDetach(Observer){ public void Detach(Observer) { _observers.Remove(o); } publicvoidNotify(){ ListIterator i(_observers); for(i.First();!i.IsDone();i.Next()){ i.CurrentItem().Update(this); } } privateList_observers; }; publicclassClockTimer extendsSubject{ publicClockTimer(){} publicint GetHour(){} publicint GetMinute(){} public int GetMinute() {} publicint GetSecond(){} publicvoidTick(){ //updateinternaltimestate //... Notify(); } };
Samplecode(continued)
publicclassDigitalClock extendsWidget implementsObserver{ publicDigitalClock(ClockTimer s){ _subject=s; _subject.Attach(this); } publicvoidUpdate(Subjects){ bl d d ( b ){ if(s==_subject){ Draw(); } } publicvoidDraw(){ int hour=_subject.GetHour(); int minute= _subject.GetMinute(); //etc. } privateClockTimer _subject; }; //clientcode ClockTimer timer=newClockTimer; DigitalClock digitalClock =new l l k( ) DigitalClock(timer);
17
18
2/16/2012
5.Strategy
Documenteditorexample:needtobreak streamoftextintolines Needtoencapsulatealgorithms
Samplecode
publicclassComposition{ publicComposition(Compositor c){_compositor=c;} publicvoidRepair(){ . int breakCount = _compositor.Compose(); . } privateCompositor_compositor; Component_components; //thelistofcomponents int _componentCount; int _lineWidth; List_lineBreaks; int _lineCount; };
19
publicabstractclassCompositor{ publicint Compose(Coord natural[],Coord stretch[],Coord shrink[],int componentCount,int lineWidth,int breaks[]); }; publicclassSimpleCompositor p { extendsCompositor{ publicSimpleCompositor(){} publicint Compose(){} //... } }; //andothertypesofcompositor //client Compositionquick=new Composition(new SimpleCompositor);
20
6.Templatemethod
Application:opendocumentstoredinfiles Document:storeinformation Howtoopenadocument? Templatemethod:definesanalgorithmintermsofabstract operationsthatsubclassesoverride toprovideconcrete behavior. b h i
Templatemethod:OpenDocument
publicclassApplication{ voidOpenDocument (conststringname){ if(!CanOpenDocument(name)){ //cannothandlethisdocument return; } Documentdoc=DoCreateDocument(); if(doc){ _docs.AddDocument(doc); AboutToOpenDocument(doc); doc.Open(); doc.DoRead(); } }
21
22
7.Visitor
Abstractsyntaxtree(AST)inacompiler. NodesinASThavedifferenttypes Confusing:mixingcodefordifferentpurpose
Visitor
Idea:nodesacceptsvisitor. Twoclasshierarchy. Onevisitmethodforeachnodeinnodes hierarchy.
23
24
2/16/2012
Samplecode
publicclassEquipment{ publicconststringName(){ return_name; } publicWattPower(){} publicCurrencyNetPrice(){} publicCurrencyDiscountPrice(){} public Currency DiscountPrice() {} publicvoid Accept(EquipmentVisitor){} protectedEquipment(const string); privatestring_name; }; publicinterfaceEquipmentVisitor { publicvoid VisitFloppyDisk(FloppyDisk); publicvoidVisitCard(Card); publicvoidVisitChassis(Chassis); publicvoidVisitBus(Bus); }; //floppydisk publicclassFloppyDisk extends Equipment{ publicvoidAccept (EquipmentVisitor visitor){ visitor.VisitFloppyDisk(this); } }
25
Moresamplecode
publicclassChassisextends Equipment{ publicvoidAccept (EquipmentVisitor visitor){ for(ListIterator i(_parts); !i.IsDone();i.Next()){ i.CurrentItem().Accept(visitor); i CurrentItem() Accept(visitor); } visitor.VisitChassis(this); } } publicclassPricingVisitor implementsEquipmentVisitor { publicPricingVisitor(){} CurrencyGetTotalPrice(){} voidVisitFloppyDisk(FloppyDisk e){ _total+=e.NetPrice(); } voidVisitCard(Card){} voidVisitChassis(Chassis){} voidVisitBus(Bus){} //... privateCurrency_total; }; //client Equipmentcomponent; PricingVisitor visitor; Component.Accept(visitor); printvisitor.GetTotalPrice();
26
8.ChainofResponsibility
Avoidcouplingofthesenderofarequestto thereceiverbygivingmorethanoneobjecta chancetohandletherequest
Example:contextsensitivehelpofGUI
Whentouse?
Morethanoneobjectcanhandleit;whichoneisnot knownapriori. Whattoinitiatearequestwithoutspecifyingreceiver Setofobjectsforhandlingtherequestshouldbe specifieddynamically
27 28
Samplecode
PublicclassHelpHandler {public HelpHandler(HelpHandler,Topic= NO_HELP_TOPIC); publicbool HasHelp(){ return_topic!=NO_HELP_TOPIC;} publicvoidSetHandler(HelpHandler, Topic); publicvoidHandleHelp(){ bli id H dl H l () { if(_successor!=null){_successor >HandleHelp();} } privateHelpHandler _successor; PrivateTopic_topic;}; PublicclassWidgetextendsHelpHandler{ } PublicclassButtonextendWidget{public voidHandleHelp if(HasHelp()){//offer helponthebutton}else{ super.HandleHelp();} } }; PublicclassDialogextendsWidget{ publicvoidHandleHelp if (H H l ()) { // bli id H dl H l if(HasHelp()){// offerhelpontheDialog}else{ super.HandleHelp();} } } constTopicPRINT_TOPIC=1;constTopic PAPER_ORIENTATION_TOPIC=2; Dialogdialog=newDialog(application, PRINT_TOPIC); Buttonbutton=newButton(dialog, PAPER_ORIENTATION_TOPIC);
29
9.State
Allowanobjecttoalterbehaviorwhenits internalstatechanges
Example:networkcommunicationinTCP/IP.
30
2/16/2012
StatePattern
Applicablewhen.
Anobjectbehaviordependsonitsstate,andit mustchangeitsbehavioratruntimedepending onthatstate. Operationshavelarge,multipartconditional statementsthatdependsonobjectsstate.Inthis case,statepatternputseachbranchofthe conditionalinseparateclasses.
Discussion
Encapsulationofchanges.
Iterator isforaccessofcomponents. Strategyisforalgorithm. Mediatorisforinterconnection.
Decouplesendersandreceivers.
Command,observer,mediator,chainofresponsiblity
31