第九章 行为型模式.doc_第1页
第九章 行为型模式.doc_第2页
第九章 行为型模式.doc_第3页
第九章 行为型模式.doc_第4页
第九章 行为型模式.doc_第5页
已阅读5页,还剩178页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

目录第九章 行为模式4.1 CHAIN OF RESPONSIBILY(职责链)对象行为型模式4.1.1 意图4.1.2 别名5.1.3 动机5.1.4 适用性5.1.5 结构58.1.6 参与者5.1.7 协作8.1.8 优点和缺点(效果)8.1.9 实现8.1.10 代码示例9.1.11 已知应用9.1.12 相关模式9.1.13 练习9.2 COMMAND(命令)对象行为型模式13.2.1 意图13.2.2 别名13.2.3 动机13.2.4 适用性13.2.5 结构13.2.6 参与者14.2.7 协作14.2.8 效果14.2.9 实现14.2.10 代码示例14.2.11 已知应用14.2.12 相关模式14.2.13 练习15.3 INTERPRETER(解释器)类行为型模式15.3.1 意图15.3.2 别名15.3.3 动机15.3.4 适用性15.3.5 结构16.3.6 参与者16.3.7 协作18.3.8 效果18.3.9 实现18.3.10 代码示例18.3.11 已知应用19.3.12 相关模式19.3.13 练习19.4 ITERATOR(迭代器)对象行为型模式23.4.1 意图23.4.2 别名23.4.3 动机23.4.4 适用性24.4.5 结构24.4.6 参与者24.4.7 协作27.4.8 效果28.4.9 实现28.4.10 代码示例28.4.11 已知应用28.4.12 相关模式28.4.13 练习28. MEDIATOR(中介者)对象行为型模式42.1 意图42.2 别名42.3 动机42.4 适用性42.5 结构43.6 参与者43.7 协作46.8 效果46.9 实现47.10 代码示例47.11 已知应用47.12 相关模式47.13 练习47. MEMENTO(备忘录)对象行为型模式51.1 意图51.2 别名51.3 动机52.4 适用性52.5 结构52.6 参与者52.7 协作55.8 效果55.9 实现55.10 代码示例55.11 已知应用56.12 相关模式56.13 练习56.7 OBSERVER(观察者)对象行为型模式60.7.1 意图60.7.2 别名60.7.3 动机60.7.4 适用性60.7.5 结构61.7.6 参与者61.7.7 协作64.7.8 效果64.7.9 实现64.7.10 代码示例64.7.11 已知应用65.7.12 相关模式65.7.13 练习65.8 STATE(状态)对象行为型模式69.8.1 意图69.8.2 别名69.8.3 动机69.8.4 适用性69.8.5 结构69.8.6 参与者70.8.7 协作72.8.8 效果72.8.9 实现73.8.10 代码示例73.8.11 已知应用73.8.12 相关模式73.8.13 练习73.STRATEGY (策略)对象行为型模式81.1 意图81.2 别名81.3 动机81.4 适用性81.5 结构82.6 参与者82.7 协作85.8 效果85.9 实现85.10 代码示例85.11 已知应用86.12 相关模式86.13 练习86. METHOD(模板方法)类行为型模式96.1 意图96. .2 别名96. .3 动机96. .4 适用性96. .5 结构96. .6 参与者97. .7 协作100. .8 效果100. .9 实现100. .10 代码示例100. .11 已知应用100. .12 相关模式100. .13 练习101. VISITOR(访问者)对象行为型模式109.1 意图109. .2 别名109. .3 动机109. .4 适用性110. .5 结构110. .6 参与者110. .7 协作114. .8 效果114. .9 实现114. .10 代码示例115. .11 已知应用115. .12 相关模式115. .13 练习115. 结构型模式的讨论120第九章 行为模式行为类模式使用继承机制在类间分派行为。本章包括两个这样的模式。 Template Method较为简单和常用。模板方法是一个算法的抽象定义,它逐步地定义该算法,每一步调用一个抽象操作或一个原语操作,子类定义抽象操作以具体实现该算法。 另一种行为类模式是Interpreter。它将一个文法表示为一个类层次,并实现一个解释器作为这些类的实例上的一个操作。 Chain of Responsibility提供更松的耦合。它让你通过一条候选对象链隐式的向一个对象发送请求。根据运行时刻情况任一候选者都可以响应相应的请求。候选者的数目是任意的,你可以在运行时刻决定哪些候选者参与到链中。 Observer模式定义并保持对象间的依赖关系。典型的Observer的例子是Smalltalk 中的模型/视图/控制器,其中一旦模型的状态发生变化,模型的所有视图都会得到通知。其他的行为对象模式常将行为封装在一个对象中并将请求指派给它。Strategy模式将算法封装在对象中,这样可以方便地指定和改变一个对象所使用的算法。Command模式将请求封装在对象中,这样它就可作为参数来传递,也可以被存储在历史列表里,或者以其他方式使用。State模式封装一个对象的状态,使得当这个对象的状态对象变化时,该对象可改变它的行为。Visitor封装分布于多个类之间的行为,而Iterator则抽象了访问和遍历一个集合中的对象的方式。.1 CHAIN OF RESPONSIBILY(职责链)对象行为型模式.1.1 意图.1.2 别名.1.3 动机.1.4 适用性.1.5 结构9.1.6 参与者l模型代码原型:/ Chain of Responsibility pattern - Structural example using System;namespace DoFactory.GangOfFour.Chain.Structural/ / MainApp startup class for Structural/ Chain of Responsibility Design Pattern./ class MainApp/ / Entry point into console application./ static void Main()/ Setup Chain of ResponsibilityHandler h1 = new ConcreteHandler1();Handler h2 = new ConcreteHandler2();Handler h3 = new ConcreteHandler3();h1.SetSuccessor(h2);h2.SetSuccessor(h3);/ Generate and process requestint requests = 2, 5, 14, 22, 18, 3, 27, 20 ;foreach (int request in requests)h1.HandleRequest(request);/ Wait for userConsole.ReadKey();/ / The Handler abstract class/ abstract class Handlerprotected Handler successor;public void SetSuccessor(Handler successor)this.successor = successor;public abstract void HandleRequest(int request);/ / The ConcreteHandler1 class/ class ConcreteHandler1 : Handlerpublic override void HandleRequest(int request)if (request = 0 & request 10)Console.WriteLine(0 handled request 1,this.GetType().Name, request);else if (successor != null)successor.HandleRequest(request);/ / The ConcreteHandler2 class/ class ConcreteHandler2 : Handlerpublic override void HandleRequest(int request)if (request = 10 & request 20)Console.WriteLine(0 handled request 1,this.GetType().Name, request);else if (successor != null)successor.HandleRequest(request);/ / The ConcreteHandler3 class/ class ConcreteHandler3 : Handlerpublic override void HandleRequest(int request)if (request = 20 & request 30)Console.WriteLine(0 handled request 1,this.GetType().Name, request);else if (successor != null)successor.HandleRequest(request);Output ConcreteHandler1 handled request 2ConcreteHandler1 handled request 5ConcreteHandler2 handled request 14ConcreteHandler3 handled request 22ConcreteHandler2 handled request 18ConcreteHandler1 handled request 3ConcreteHandler3 handled request 27ConcreteHandler3 handled request 20.1.7 协作.1.8 优点和缺点(效果).1.9 实现l.1.10 代码示例.1.11 已知应用.1.12 相关模式.1.13 练习1./ Chain of Responsibility pattern - Real World example using System;namespace DoFactory.GangOfFour.Chain.RealWorld/ / MainApp startup class for Real-World / Chain of Responsibility Design Pattern./ class MainApp/ / Entry point into console application./ static void Main()/ Setup Chain of ResponsibilityApprover larry = new Director();Approver sam = new VicePresident();Approver tammy = new President();larry.SetSuccessor(sam);sam.SetSuccessor(tammy);/ Generate and process purchase requestsPurchase p = new Purchase(2034, 350.00, Supplies);larry.ProcessRequest(p);p = new Purchase(2035, 32590.10, Project X);larry.ProcessRequest(p);p = new Purchase(2036, 122100.00, Project Y);larry.ProcessRequest(p);/ Wait for userConsole.ReadKey();/ / The Handler abstract class/ abstract class Approverprotected Approver successor;public void SetSuccessor(Approver successor)this.successor = successor;public abstract void ProcessRequest(Purchase purchase);/ / The ConcreteHandler class/ class Director : Approverpublic override void ProcessRequest(Purchase purchase)if (purchase.Amount 10000.0)Console.WriteLine(0 approved request# 1,this.GetType().Name, purchase.Number);else if (successor != null)successor.ProcessRequest(purchase);/ / The ConcreteHandler class/ class VicePresident : Approverpublic override void ProcessRequest(Purchase purchase)if (purchase.Amount 25000.0)Console.WriteLine(0 approved request# 1,this.GetType().Name, purchase.Number);else if (successor != null)successor.ProcessRequest(purchase);/ / The ConcreteHandler class/ class President : Approverpublic override void ProcessRequest(Purchase purchase)if (purchase.Amount 100000.0)Console.WriteLine(0 approved request# 1,this.GetType().Name, purchase.Number);elseConsole.WriteLine(Request# 0 requires an executive meeting!,purchase.Number);/ / Class holding request details/ class Purchaseprivate int _number;private double _amount;private string _purpose;/ Constructorpublic Purchase(int number, double amount, string purpose)this._number = number;this._amount = amount;this._purpose = purpose;/ Gets or sets purchase numberpublic int Numberget return _number; set _number = value; / Gets or sets purchase amountpublic double Amountget return _amount; set _amount = value; / Gets or sets purchase purposepublic string Purposeget return _purpose; set _purpose = value; OutputDirector Larry approved request# 2034President Tammy approved request# 2035Request# 2036 requires an executive meeting!2. .2 COMMAND(命令)对象行为型模式.2.1 意图命令(Command)模式属于对象的行为模式【GOF95】。命令模式又称为行动(Action)模式或交易(Transaction)模式。命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。.2.2 别名.2.3 动机.2.4 适用性在下面的情况下应当考虑使用命令模式:1、使用命令模式作为CallBack在面向对象系统中的替代。CallBack讲的便是先将一个函数登记上,然后在以后调用此函数。2、需要在不同的时间指定请求、将请求排队。一个命令对象和原先的请求发出者可以有不同的生命期。换言之,原先的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接收者可以是在本地,也可以在网络的另外一个地址。命令对象可以在串形化之后传送到另外一台机器上去。3、系统需要支持命令的撤消(undo)。命令对象可以把状态存储起来,等到客户端需要撤销命令所产生的效果时,可以调用undo()方法,把命令所产生的效果撤销掉。命令对象还可以提供redo()方法,以供客户端在需要时,再重新实施命令效果。4、如果一个系统要将系统中所有的数据更新到日志里,以便在系统崩溃时,可以根据日志里读回所有的数据更新命令,重新调用Execute()方法一条一条执行这些命令,从而恢复系统在崩溃前所做的数据更新。5、一个系统需要支持交易(Transaction)。一个交易结构封装了一组数据更新命令。使用命令模式来实现交易结构可以使系统增加新的交易类型。.2.5 结构.2.6 参与者命令模式涉及到五个角色,它们分别是: 客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。 命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。 具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Execute()方法,负责调用接收考的相应操作。Execute()方法通常叫做执方法。 请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。 接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。 模式原型代码:/Commandpattern-Structuralexample usingSystem; /Command abstractclassCommand /Fields protectedReceiverreceiver; /Constructors publicCommand(Receiverreceiver) this.receiver=receiver; /Methods abstractpublicvoidExecute(); /ConcreteCommand classConcreteCommand:Command /Constructors publicConcreteCommand(Receiverreceiver): base(receiver) /Methods publicoverridevoidExecute() receiver.Action(); /Receiver classReceiver /Methods publicvoidAction() Console.WriteLine(CalledReceiver.Action(); /Invoker classInvoker /Fields privateCommandcommand; /Methods publicvoidSetCommand(Commandcommand) mand=command; publicvoidExecuteCommand() command.Execute(); /*/ /Clienttest / publicclassClient publicstaticvoidMain(stringargs) /Createreceiver,command,andinvoker Receiverr=newReceiver(); Commandc=newConcreteCommand(r); Invokeri=newInvoker(); /Setandexecutecommand i.SetCommand(c); i.ExecuteCommand(); .2.7 协作.2.8 效果首先命令应当重一些还是轻一些。在不同的情况下,可以做不同的选择。如果把命令设计得轻,那么它只是提供了一个请求者和接收者之间的耦合而己,命令代表请求者实现请求。相反,如果把命令设计的重,那么它就应当实现所有的细节,包括请求所代表的操作,而不再需要接收者了。当一个系统没有接收者时,就可以采用这种做法。更常见的是处于最轻和最重的两个极端之间时情况。命令类动态地决定调用哪一个接收者类。其次是否支持undo和redo。如果一个命令类提供一个方法,比如叫unExecute(),以恢复其操作的效果,那么命令类就可以支持undo和redo。具体命令类需要存储状态信息,包括:1.接收者对象实际上实施请求所代表的操作; 2.对接收者对象所作的操作所需要的参数; 3.接收者类的最初的状态。接收者必须提供适当的方法,使命令类可以通过调用这个方法,以便接收者类恢复原有状态。 如果只需要提供一层的undo和redo,那么系统只需要存储最后被执行的那个命令对象。如果需要支持多层的undo和redo,那么系统就需要存储曾经被执行过的命令的清单,清单能允许的最大的长度便是系统所支持的undo和redo的层数。沿着清单逆着执行清单上的命令的反命令(unExecute())便是undo;沿着清单顺着执行清单上的命令便是redo。命令允许请求的一方和接收请求的一方能够独立演化,从而且有以下的优点: 命令模式使新的命令很容易地被加入到系统里。 允许接收请求的一方决定是否要否决(Veto)请求。 能较容易地设计-个命令队列。 可以容易地实现对请求的Undo和Redo。 在需要的情况下,可以较容易地将命令记入日志。 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。 命令类与其他任何别的类一样,可以修改和推广。 你可以把命令对象聚合在一起,合成为合成命令。比如宏命令便是合成命令的例子。合成命令是合成模式的应用。 由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。命令模式的缺点如下: 使用命令模式会导致某些系统有过多的具体命令类。某些系统可能需要几十个,几百个甚至几千个具体命令类,这会使命令模式在这样的系统里变得不实际。.2.9 实现.2.10 代码示例1下面的代码使用命令模式演示了一个简单的计算器,并允许执行undo与redo。注意:operator在C#中是关键词,所以在前面添加一个将其变为标识符。/Commandpattern-RealWorldexample usingSystem; usingSystem.Collections; /Command abstractclassCommand /Methods abstractpublicvoidExecute(); abstractpublicvoidUnExecute(); /ConcreteCommand classCalculatorCommand:Command /Fields charoperator; intoperand; Calculatorcalculator; /Constructor publicCalculatorCommand(Calculatorcalculator, charoperator,intoperand) this.calculator=calculator; this.operator=operator; this.operand=operand; /Properties publiccharOperator setoperator=value; publicintOperand setoperand=value; /Methods overridepublicvoidExecute() calculator.Operation(operator,operand); overridepublicvoidUnExecute() calculator.Operation(Undo(operator),operand); /Privatehelperfunction privatecharUndo(charoperator) charundo=; switch(operator) case+:undo=-;break; case-:undo=+;break; case*:undo=/;break; case/:undo=*;break; returnundo; /Receiver classCalculator /Fields privateinttotal=0; /Methods publicvoidOperation(charoperator,intoperand) switch(operator) case+:total+=operand;break; case-:total-=operand;break; case*:total*=operand;break; case/:total/=operand;break; Console.WriteLine(Total=0(following12), total,operator,operand); /Invoker classUser /Fields privateCalculatorcalculator=newCalculator(); privateArrayListcommands=newArrayList(); privateintcurrent=0; /Methods publicvoidRedo(intlevels) Console.WriteLine(-Redo0levels,levels); /Performredooperations for(inti=0;ilevels;i+) if(currentcommands.Count-1) (Command)commandscurrent+).Execute(); publicvoidUndo(intlevels) Console.WriteLine(-Undo0levels,levels); /Performundooperations for(inti=0;i0) (Command)commands-current).UnExecute(); publicvoidCompute(charoperator,intoperand) /Createcommandoperationandexecuteit Commandcommand=newCalculatorCommand( calculator,operator,operand); command.Execute(); /Addcommandtoundolist commands.Add(command); current+; /*/ /CommandApptest / publicclassClient publicstaticvoidMain(stringargs) /Createuserandlethercompute Useruser=newUser(); user.Compute(+,100); user.Compute(-,50); user.Compute(*,10); user.Compute(/,2); /Undoandthenredosomecommands user.Undo(4); user.Redo(3); .2.11 已知应用1.使用设计模式实现Undo,Redo框架 分类: C+ 2008-12-10 13:38 586人阅读 评论(0) 收藏 举报 编辑器程序少不了要支持undo, redo功能,如何实现?本文就是参考了设计模式中给出的思路实现了一个。这里主要用到了两个模式:命令(command)模式, 备忘录(memento)模式所谓编辑,功能上可以分成3个原子操作:添加新内容,编辑已有内容,删除已有内容, 因此编辑功能3个command实现,AddCommand, EditCommand, DeleteCommand. 这3个命令实现了相同的接口do, undo.先说一下代码的风格,自从使用WTL,就喜欢上了WTL的代码风格,本文就是仿照WTL风格写的.先看一下Command的接口:1. classCCommand 2. 3.4. public: 5. virtualCCommand(); 6.7. public: 8. virtualboolDo()=0; 9. virtualboolUndo()=0; 10. virtualboolCanUndo()=0; 11.12. ; 13.AddCommand, EditCommand, DeleteCommand都实现了这个接口类。下面WTL风格代码开始了:先留个空架子1. template 2. classCCommandImplBase:publicTBase 3. 4. 先空着,以后留着扩展 5. ;下面是主要实现:用到了event, 当Command执行时会触发event,你可以在时间里做一些诸如试图更新, 所谓event,跟C#里的事件相似,感兴趣的可以看我前面的文章用C+模拟C#事件机制。1. templateclassT,classTBase=CCommand,classTTraits=CommandTraits 2. classCCommandImpl:publicCCommandImplBase 3. 4. public: 5. typedefTTraits:CmdEventCmdEvent; 6. typedefCmdEvent:EventHandlerEventHandler; 7.8. public: 9. CCommandImpl(typenameCmdEvent:EventArgs/*const&*/

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论