1、单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2013/6/6,#,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2013/6/6,#,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2013/6/6,#,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2013/6/6,#,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2013/6/6,#,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2013/6
2、/6,#,单击此处编辑母版标题样式,2013/6/6,#,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2013/6/6,#,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2013/6/6,#,READY?,Now Loading,C,O,A,MM,N,D,命令模式,对象行为型模式,内容简介,命令模式粗识,概述,结构简述,第一部分,第二部分,第三部分,模式细解,模式详解,实例解析,第一部分,第二部分,第三部分,实际应用,效果,&,优缺点
3、使用注意,相关模式,应用,第一部分,第二部分,第三部分,命令模式粗识,概述,结构简述,第一部分,第二部分,第三部分,杨虎刚,如何开空调?,对于使用空调的,客户,就是我们来说,开机确实很简单,按下遥控,按钮,,然后耐心等待就可以了。,但是,当按下启动按钮过后呢?,谁来处理?如何处理?,经历了怎样的过程,才让空调启动起来?,也就是说,客户只管发出命令,,谁实现命令,如何实现,,客户是不关心的。,如何开空调,空调最终是由空调哪个部件打开,客户是不知道的。,Command,模式,动机,有时必须向,某对象,提交,请求,但并不知道关于,被请求的操作,的任何信息,或,请求接受者,的任何信息,意图,将,
4、请求,封装,为一个,对象,,,从而使你可,用,不同的请求,对,客户,进行,参数化,。,对请求排队或记录请求日志,,以及支持可撤销操作。,Client,:创建具体的命令对象,并且设置命令对象的接收者。注意这个,不是常规,意义上的客户端,而是在组装命令对象和,接收者。,Command,:,定义命令的接口,声明执行的方法,。,ConcreteCommand,:,命令接口实现对象,是,“,虚,”,的,实现。,Receiver,:,接收者,真正执行命令的对象,。,Invoker,:,要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象,。,2026/6/28 周日,协作图,2026/6/28
5、 周日,协作图,模式细解,模式详解,实例解析,第一部分,第二部分,第三部分,孙冉,刚才讲到的通用,Command,类图,Command,public,interface,Command,void,Execute,();,打开空调,Command,public,class,打开空调,Command,:,Command,空调,airCondition,;,public,打开空调,Command(,空调,airCondition),this,.airCondition=airCondition;,public,void,Execute(),/,注意,你可以在,Execute(),中添加多个方法,ai
6、rCondition.Start();,关闭空调,Command,public,class,关闭空调,Command,:,Command,空调,airCondition;,public,关闭空调,Command(,空调,airCondition),this,.airCondition=airCondition;,public,void,Execute(),airCondition.Stop();,Invoker,public,class,遥控器,private,Command,onCommand;,public,void,执行,(),onCommand.Execute();,public,vo
7、id,SetCommand(,Command,onCommand),this,.onCommand=onCommand;,Receiver,public,class,空调,/,接受者,public,void,Start(),Console,.WriteLine(,空调打开了,);,public,void,Stop(),Console,.WriteLine(,空调关上了,);,Client,static,void,Main(,string,args,),string,str=,;,空调,airCondition=,new,空调,();,遥控器,panel=,new,遥控器,();,Command
8、aironCommand=,new,打开空调,Command,(airCondition);,Command,airoffCommand=,new,关闭空调,Command,(airCondition);,Console,.WriteLine(,1.,开空调,2.,关空调,3.,退出,);,while,(str!=,3,),str=,Console,.ReadLine();,if,(str=,1,),panel.SetCommand(aironCommand);,panel.,执行,();,if,(str=,2,),panel.SetCommand(airoffCommand);,panel
9、执行,();,Command,public,interface,Command,void,Execute();,void,undo();,打开空调,Command,public,class,打开空调,Command,:,Command,空调,airCondition;,public,打开空调,Command(,空调,airCondition),this,.airCondition=airCondition;,public,void,Execute(),/,注意,你可以在,Execute(),中添加多个方法,airCondition.Start();,public,void,undo(),C
10、onsole,.WriteLine(,撤销 空调打开了,);,Invoker,public,class,遥控器,List,undolist=,new,List,();,List,redolist=,new,List,();,private,Command,onCommand;,public,void,执行,(),onCommand.Execute();,undolist.Add(onCommand);,public,void,SetCommand(,Command,onCommand),this,.onCommand=onCommand;,Invoker,public,void,撤销,(),i
11、f,(undolist.Count=0),Console,.WriteLine(,已经不能在撤销了,);,else,redolist.Add(undolistundolist.Count-1);,undolistundolist.Count-1.undo();,undolist.Remove(undolistundolist.Count-1,);,Invoker,public,void,恢复,(),if,(redolist.Count=0),Console,.WriteLine(,已经不能在恢复了,);,else,undolist.Add(redolistredolist.Count-1);,
12、redolistredolist.Count-1.Execute();,redolist.Remove(redolistredolist.Count-1);,Client,class,Program,static,void,Main(,string,args),ArrayList,list1=,new,ArrayList,();,string,str=,;,空调,空调,=,new,空调,();,电视,电视,=,new,电视,();,遥控器,遥控器,=,new,遥控器,();,Command,打开空调,=,new,打开空调,Command,(,空调,);,Command,关上空调,=,new,关
13、闭空调,Command,(,空调,);,Command,打开电视,=,new,打开电视,Command,(,电视,);,Command,关上电视,=,new,关闭电视,Command,(,电视,);,Console,.WriteLine(,请输入,1,、,2,、,3,、,4,、,5,、,6,、,7,、,8,:,);,Console,.WriteLine(,1,代表打开电视*,2,代表关上电视*,3,代表打开空调,);,Console,.WriteLine(,4,代表关上空调*,5,代表撤销操作*,6,重做*,7,退出,);,Client,while,(str!=,7,),str=,Consol
14、e,.ReadLine();,if,(str=,1,),list1.Add(,a,);,遥控器,.SetCommand(,打开电视,);,遥控器,.,执行,(),;,else,if,(str=,5,),遥控器,.,撤销,();,else,if,(str=,6,),遥控器,.,恢复,();,实际应用,效果,&,优缺点,使用须知,应用,第一部分,第二部分,第三部分,杜宗轩,适用性,如果你有这些需要,支持修改、取消操作功能时,用构建在原语操作上的高层操作构造系统,在不同时刻指定、排列和执行请求,支持记录操作日志时,通过网络将命令发给其他机器,写界面菜单等时,代替面向过程语言,中的,Call Back
15、机制,CallBack,讲的便是先将一个函数登记上,然后在以后调用此函数。,因为使用此函数可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。,简而言之,回调函数就是允许用户把需要调用的方法的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。,运用 效果,Command,模式将调用操作的对象与知道如何实现该操作的对象解耦。,Command,是头等的对象。,它们可以像其他对象一样被操纵和扩展,你可以将多个命令装配成一个复合命令。,增加新的,Command,很容易,因为这无需改变已有的类。,实现,考虑要
16、点,所谓命令模式的根本思想就是:,先形成命令,在根据命令执行。,理解思想,不要机械的照搬。消化成自己的,要支持,Undo,和,Redo,的话,需要一个表,-,对表的操作,避免取消操作过程中的错误积累,优点,解耦,了发送者和接受者之间联系,同时,Command,模式可控性不强,如果要为所有,Service,动态增加类似,Filter,等这样通用功能,如权限检查等是非常不方便的。,结构复杂,,代码实现可能会不方便,缺点,会导致某些系统有过多的具体命令类,。,可以很容易的记录操作日志,和进行撤销,重做操作,能较容易地建立一个命令队列;,。,相关模式,命令模式,组成模式,需求:,有,个固定命令组合会多
17、次被,执行,解决:,加入组成模式,,定义一个宏命令,类,实现方法,publicclassMacroCommandimplementsCommand,privateListcmdList=newArrayList,();,publicadd(Commandcommand,),cmdList.add(command,);,publicremove(Commandcommand,),cmdList.remove(command,);,publicvoidexecute,(),Commandcmd,;,for(inti=0;icmdList.size();i,+),cmd=(Command)cmdLi
18、st.get(i,);,cmd.execute,();,使用时可以将,MacroCommand,当做普通命令使用。,请求角色并不知道这是一个宏命令。,命令模式,备忘录,模式,需求,:需要加入,redo undo,操作,解决,:加入备忘录,模式,简单实现,public,class ConcreteCommandOne implements Command,private Receiver,receiver;,private Receiver lastReceiver;,public ConcreteCommandOne(Receiver receiver),this.receiver=recei
19、ver;,public void execute(),record();,receiver.actionOne();,public void undo(),/,恢复状态,public void redo(),lastReceiver.actionOne();,public record(),/,记录状态,应用,替代,if,、,else,面向过程设计和面向对象设计的一个区别就是:,是否在业务逻辑层使用冗长的,if else,判断。,传统思维习惯的分析,面向过程分析,是顺向向下的分析,像流下的水流。,而在面向对象设计中,要求打破从上到下的顺序过程,程序的执行过程有,OO,决定,由事物决定。,替代,
20、if,、,else,用,Command,模式做切换这样可以让代码没那么多逻辑分支,用,Command,命令控制到不同的操作分离判断。,为程序提供更清晰的层次结构。,其他,模拟银行系统,短信互动程序,文档编辑器,简化,Command,模式,命令模式的角色比较多,,在实际应用中可以根据所需要的,功能和不需要的功能加以简化。,1,去掉 调用者,产生命令集合后,我们可以直接在,client,中迭代执行执行操作,简化,Command,模式,2,变化 调用者 成为 跟踪者,public class Invoker /,调用者,List commands;/,已经执行完毕的命令集合,public void addCommand(Command command,int i),commands.add(i,command);,public void action(Command command)/,执行操作,command.execute();,commands.add(command);,这样这个类就记录了所有执行过的操作。,简化,Command,模式,3,去掉执行者:,直接在命令中(,execute,方法中)加业务逻辑。,(这样只适合于简单的小的系统,.,),END,






