命令模式.ppt

上传人:laozhun 文档编号:2383054 上传时间:2023-02-16 格式:PPT 页数:41 大小:3.06MB
返回 下载 相关 举报
命令模式.ppt_第1页
第1页 / 共41页
命令模式.ppt_第2页
第2页 / 共41页
命令模式.ppt_第3页
第3页 / 共41页
命令模式.ppt_第4页
第4页 / 共41页
命令模式.ppt_第5页
第5页 / 共41页
点击查看更多>>
资源描述

《命令模式.ppt》由会员分享,可在线阅读,更多相关《命令模式.ppt(41页珍藏版)》请在三一办公上搜索。

1、命令模式,将把封装带到一个全新的境界:把方法调用(method invocation)封装起来通过封装方法调用,可以把运算块包装成形通过封装方法调用,也可以做一些很聪明的事情,例如记录日志,或者重复使用这些封装来实现撤销(undo),封装调用,巴斯特家电自动化公司,设计一个家电自动化遥控器的API附上一个创新控制器的原型以供研究这个遥控器具有7个可编程的插槽(每个都可以指定到一个不同的家电装置)每个插槽都有对应的开关按钮这个遥控器还具备一个整体的撤销按钮在光盘里附上有一组Java类,这些类是由多家厂商开发出来的,用来控制家电自动化装置,例如电灯、风扇、热水器、音响设备和其他类似的可控制装置希望

2、能够创建一组控制遥控器的API,让每个插槽都能够控制一个或一组装置,让硬件解脱!让我们看看这个遥控器,看一下厂商的类,思考,目前有一个附着开和关按钮的简单遥控器,还有一套五花八门的厂商类有许多类都具备on()和off()方法,除此之外,还有一些方法像是dim(),setTemperature(),setVolumn(),setDirection()要把它看成分离的关注点:遥控器应该知道如何解读按钮被按下的动作,然后发出正确的请求,但是遥控器不需知道这些家电自动化的细节,或者如何打开热水器但如果遥控器很笨,只知道如何做出一般的要求,那又怎能设计出让这个遥控器能够调用一些诸如打开电灯或车库门的动作

3、?,不必让遥控器知道太多厂商类的细节不想让遥控器包含一大堆if语句,例如“if slot1=Light,then light.on(),else if slot1=Hottub then hottob.jetsOn()”如果这样设计的话,只要有新的厂商类进来,就必须修改代码命令模式可将“动作的请求者”从“动作的执行者”对象中解耦,请求者可以是遥控器,而执行者对象就是厂商类其中之一的实例,在设计中采用“命令对象”。利用它,把请求(例如打开电灯)封装成一个特定对象(例如客厅电灯对象)。如果对每个按钮都存储一个命令对象,那么当按钮被按下时,就可以请命令对象做相关的工作遥控器并不需要知道工作内容是什么

4、,只要有个命令对象能和正确的对象沟通使用模式,能够创建一个API,将这些命令对象加载到按钮插槽,让遥控器的代码尽量保持简单。而把家电自动化的工作和进行该工作的对象一起封装在命令对象中这个模式可以同时设计“撤销按钮”,餐厅,餐厅的角色和职责,一张订单封装了准备餐店的请求把订单想象成一个用来请求准备餐点的对象,和一般的对象一样,订单对象可以被传递:从女招待传递到订单柜台,或者从女招待传递到接替下一班的女招待订单的接口只包含一个方法,也就是orderUp()这个方法封装了准备餐点所需的动作订单内有一个到“需要进行准备工作的对象”(也就是厨师)的引用这一切都被封装起来,所以女招待不需要知道订单上有什么

5、,也不需要知道是谁来准备餐点;她只需要将订单放到订单窗口,然后喊一声“订单来了”就可以了,女招待的工作是接受订单,然后调用订单的orderUp()方法女招待的工作很简单:接下顾客的订单,继续帮助下一个顾客,然后将一定数量的订单放到订单柜台,并调用orderUp()方法,让人来准备餐点女招待其实不必担心订单的内容是什么,或者由谁来准备餐点她只需要知道,订单有一个orderUp()方法可以调用现在,一天内,不同的顾客有不同的订单,这会使得女招待的takeOrder()方法被传入不同的参数女招待知道所有的订单都支持orderUp()方法,任何时候她需要准备餐点时,调用这个方法,快餐厨师具备准备餐点的

6、知识,快餐厨师是一种对象,他真正知道如何准备餐点一旦女招待调用orderUp()方法,快餐厨师就接手,实现需要创建餐点的所有方法请注意,女招待和厨师之间是彻底的解耦:女招待的订单封装了餐点的细节,她只要调用每个订单的方法即可,而厨师看了订单就知道该做些什么餐点;厨师和女招待之间从来不需要直接沟通,重点,把餐厅想成是OO设计模式的一种模型,而这个模型允许将“发出请求的对象”和“接受与执行这些请求的对象”分隔开来对于遥控器API,我们需要分隔开“发出请求的按钮代码”和“执行请求的厂商特定对象”万一遥控器的每个插槽都持有一个像餐厅订单那样的对象,会怎么样?那么,当一个按钮被按下,只要调用该对象的or

7、derUp()方法,电灯就开了,而遥控器不需要知道事情是怎么发生的,也不需要知道涉及哪些对象现在我们就把餐厅的对话换成命令模式,从餐厅到命令模式,加载调用者,客户创建一个命令对象客户利用setCommand()将命令对象储存在调用者中稍后客户要求调用者执行命令。请注意:一旦命令被加载到调用者,该命令可以被使用并丢弃,或者可以被保留下来并使用许多次,连连看,餐厅命令模式,女招待Command快餐厨师execute()orderUp()Client订单Invoker顾客ReceivertakeOrder()setCommand(),第一个命令对象,实现命令接口(餐厅例子中是orderUp(),现在

8、改为惯用名称execute)public interface Command public void execute();实现一个打开电灯的命令现在,假设想实现一个打开电灯的命令。根据厂商所提供的类,public class LightOffCommand implements Command Light light;public LightOffCommand(Light light)this.light=light;public void execute()light.off();,使用命令对象,让我们把这一切简化:假设我们有一个遥控器,它只有一个按钮和对应的插槽,可以控制一个装置publ

9、ic class SimpleRemoteControl Command slot;public SimpleRemoteControl()public void setCommand(Command command)slot=command;public void buttonWasPressed()slot.execute();,遥控器使用的简单测试,public class RemoteControlTest public static void main(String args)SimpleRemoteControl remote=new SimpleRemoteControl();L

10、ight light=new Light();LightOnCommand lightOn=new LightOnCommand(light);remote.setCommand(lightOn);remote.buttonWasPressed();,练习,实现GarageDoorOpenCommand修改RemoteControlTest,定义命令模式,命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象命令模式也支持可撤销的操作一个命令对象通过在特定接收者上绑定一组动作来封装一个请求命令对象将动作和接收者包进对象中这个对象只暴露出一个execute()方法,当此方

11、能被调用的时候,接收者就会进行这些动作从外面来看,其他对象不知道究竟哪个接收者进行了哪些动作,只知道如果调用execute()方法,请求的目的就能达到,利用命令来参数化对象的一些例子再回到餐厅,一整天下来,女招待参数化许多订单在简单遥控器中,我们先用一个“打开电灯”命令加载按钮插槽,稍后又将命令替换成为另一个“打开车库门”命令就和女招待一样,遥控器插槽根本不在乎所拥有的是什么命令对象,只要该命令对象实现了Command接口就可以了,类图,在简单遥控器(SimpleRemote)中所做的一样需要提供一个方法,将命令指定到插槽实际上,我们有7个插槽,每个插情都具备开和关按钮,所以我们可以用类似方式

12、,把命令指定给遥控器,像这样onCommands0=onCommand;offCommands0=offCommand;,将命令指定到插槽,将遥控器的每个插槽,对应到一个命令这样就让遥控器变成“调用者”当按下按钮,相应命令对象的execute()方法就会被调用,其结果就是,接受者(例如:电灯、天花板电扇、音响)的动作被调用,实现遥控器RemoteControl实现命令LightOffCommandStereoOnWithCDCommand逐步测试遥控器RemoteLoader,撤销的功能,当命令支持撤销时,该命令就必须提供和execute()方法相反的undo()方法不管execute()刚才

13、做什么,undo()都会倒转过来在各个命令中加入undo()之前,我们必须先在Command接口中加入undo()方法public interface Command public void execute();public void undo();,从LightOnCommand开始下手:如果LightOnCommand的execute()方法被调用,那么最后被调用的是on()方法undo()需要调用off()方法进行相反的动作LightOnCommandLightOffCommand要加上对撤销按钮的支持,必须对遥控器类做一些小修改我们打算这么做:加入一个新的实例变量,用来追踪最后被调用的

14、命令,然后,不管何时撤销按钮被按下,我们都可以取出这个命令并调用它的undo()方法RemoteControlWithUndoQARemoteLoader,使用状态实现撤销,实现电灯的撒销是有意义的,但也实在是太容易了通常,想要实现撤销的功能,需要记录一些状态让我们试一个更有趣的例子,比方说厂商类中的天花板上的吊扇吊扇允许有多种转动速度,当然也允许被关闭CeilingFan,加入撤销到吊扇的命令类,让我们把撤销加入天花板吊扇的诸多命令中需要追踪吊扇的最后设置速度,如果undo()方法被调用了,就要恢复成之前吊扇速度的设置值CeilingFanHighCommand如何实现low(低速)、med

15、ium(中速)、off(关闭),准备测试天花板吊扇,RemoteLoader,每个遥控器都需具备Party模式,如果拥有了一个遥控器,却无法光凭按下一个按钮,就同时能弄暗灯光、打开音响和电视、设置好DVD.并让热水器开始加温,那么要这个遥控器还有什么意义?制造一种新的命令,用来执行其他一堆命令,而不只是执行一个命令,MacroCommand,public class MacroCommand implements Command Command commands;public MacroCommand(Command commands)mands=commands;public void ex

16、ecute()for(int i=0;i commands.length;i+)commandsi.execute();,使用宏命令,先创建想要进入宏的命令集合:Light light=new Light(Living Room);TV tv=new TV(“Living Room”);Stereo stereo=new Stereo(Living Room);Hottub hottub=new Hottub();LightOnCommand lightOn=new LightOnCommand(light);StereoOnCommand stereoOn=new StereoOnComma

17、nd(stereo);TVOnCommand tvOn=new TVOnCommand(tv);HottubOnCommand hottubOn=new HottubOnCommand(hottub);,按下来创建两个数组,其中一个用来记录开启命令,另一个用来记录关闭命令,并在数组内放入对应的命令:Command partyOn=lightOn,stereoOn,tvOn,hottubOn;Command partyOff=lightOff,stereoOff,tvOif,hottubOff;MacroCommand partyOnMacro=new MacroCommand(partyOn)

18、;MacroCommand partyOffMacro=new MacroCommand(partyOff);,然后将宏命令指定给我们所希望的按钮remoteControl.setCommand(0,partyOnMacro,partyOffMacro);最后,只需按下一些按钮,测试是否正常工作System.out.println(remoteControl);System.out.println(-Pushing Macro On-);remoteControl.onButtonWasPushed(0);System.out.println(-Pushing Macro Off-);remoteControl.offButtonWasPushed(0);,撤销功能,Any Question?,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号