《6》命令模式

来源:互联网 发布:linux 韦东山 编辑:程序博客网 时间:2024/05/29 12:29

命令模式的主线任务:

把命令封装成对象




=========基础篇

=========


问题:

一个家电遥控器,两排4个按钮,客户提供许多家电类(LightCDTV。。。);

要求:

设计遥控器控制家电运行,



上类图:


可能有人喜欢非专业的:





理解:


用户先获取receiver对象,例如:light(客户提供的);

用户(Client类)创建对应的commandreceiver)对象,例如:LightOnCommand

Client调用遥控器类(Invoker),向其设置LightOnCommand对象;

遥控器调用command.execute();

Light执行light.on()




上代码:


先看Client,把大体流程记住:

public class Client {public static void main(String[] args) {//创建receiverLight light = new Light();CDMachine CD = new CDMachine();//new commandCommand lightOnCommand = new LightOnCommand(light);Command CDCommand = new CDMachineOnCommand(CD);//设置Command到遥控器(invoker)按钮位置RemoteControl ctl = new RemoteControl();ctl.setCommand(lightOnCommand, 0);ctl.setCommand(CDCommand, 1);//遥控器按钮按下ctl.onButtonClick(0);ctl.onButtonClick(1);}}

Receiver(Light为例)

public class Light {void on(){System.out.println("light on");}void off(){System.out.println("light off");}}

Command

public interface Command {void execute();}public class LightOnCommand implements Command{private Light receiver;public LightOnCommand(Light receiver){this.receiver = receiver;}@Overridepublic void execute() {receiver.on();}}



remoteControl

public class RemoteControl {//模拟4个按钮private Command[] buttons = new Command[4];public void setCommand(Command command,int pos){//忽略pos错误检查buttons[pos] = command;}void onButtonClick(int pos){buttons[pos].execute();}}


看测试结果:

//

lighton

//CD

power

setCD

Machinestart









给出命令模式定义:

将“命令”封装成对象,以便使用不同的请求、队列、日志来参数化对象,同时还提供撤销操作



定义中“参数化”理解:

以本文中例子解释,使用LightOnCommand&LightOffCommandlight参数化。

即:相当于将light分解成可传递的命令参数



优点:

1》方便后期替换修改按钮的命令,只需set一下

2》方便使用撤销,前进、后退功能,因为:可以记录命令的执行

3》因为记录命令,会有一个遥控器的运行日志,移到PC机上,就是还原的功能啦


缺点:

会有大量的command类,造成代码复杂






=========小应用

=========



说明:

拓展一个撤销and恢复的功能,类似于word文档上的撤销,恢复

还是在remoteControl这个例子上修改


实施步骤:

修改Light成接口,理解:客厅、厨房、厕所、书房的灯要区分开来;

修改Command接口,加入unexecute()行为;

invokerremoteControl)加入记录的东西(Stack);

修改Client加入测试代码;




上代码:


Light接口:

public abstract class Light {abstract void on();abstract void off();}

Light子类:

public class Light1 extends Light{void on(){System.out.println("1 light on");}void off(){System.out.println("1 light off");}}



Command接口:

public interface Command {void execute();void unexecute();}


public class LightOnCommand implements Command{private Light receiver;public LightOnCommand(Light receiver){this.receiver = receiver;}@Overridepublic void execute() {receiver.on();}@Overridepublic void unexecute() {receiver.off();}}

修改remoteControl类(在其中加入记录栈):

public class RemoteControl {//模拟4个按钮private Command[] buttons = new Command[4];public void setCommand(Command command,int pos){//忽略pos错误检查buttons[pos] = command;}void onButtonClick(int pos){_execute(buttons[pos]);}//修改部分,加入记录Command职能private Stack<Command> executes = new Stack<>();private Stack<Command> unexecutes = new Stack<>();private void _execute(Command command){command.execute();executes.push(command);}private void _unexecute(Command command){command.unexecute();unexecutes.push(command);}//加入撤销and恢复行为public void cancel(){if(executes.isEmpty()){System.out.println("我们已经撤销到极限了");return;} _unexecute(executes.pop());}public void restore(){if(unexecutes.isEmpty()){System.out.println("我们已经没的恢复啦");return;}_execute(unexecutes.pop());}}



测试Client代码:

public class Client {public static void main(String[] args) {//new commandCommand lightOnCommand1 = new LightOnCommand(new Light1());Command lightOnCommand2 = new LightOnCommand(new Light2());Command lightOnCommand3 = new LightOnCommand(new Light3());Command lightOnCommand4 = new LightOnCommand(new Light4());//设置Command到遥控器(invoker)按钮位置RemoteControl ctl = new RemoteControl();ctl.setCommand(lightOnCommand1, 0);ctl.setCommand(lightOnCommand2, 1);ctl.setCommand(lightOnCommand3, 2);ctl.setCommand(lightOnCommand4, 3);//遥控器按钮按下(被记录)ctl.onButtonClick(0);ctl.onButtonClick(1);ctl.onButtonClick(0);ctl.onButtonClick(1);ctl.onButtonClick(2);ctl.onButtonClick(3);//撤销and恢复的测试(使用记录)ctl.cancel();ctl.cancel();ctl.cancel();ctl.cancel();ctl.cancel();ctl.cancel();ctl.cancel();ctl.restore();ctl.cancel();ctl.restore();ctl.restore();ctl.restore();ctl.restore();ctl.restore();ctl.restore();ctl.restore();}}


测试结果:

1light on

2light on

1light on

2light on

3light on

4light on


4light off

3light off

2light off

1light off

2light off

1light off

我们已经撤销到极限了


1light on

1light off

1light on

2light on

1light on

2light on

3light on

4light on

我们已经没的恢复啦




0 0