码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式 7 —— 命令模式

时间:2014-09-11 15:05:32      阅读:335      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   os   使用   ar   strong   

设计模式目录:

设计模式 1 ——观察者模式

设计模式 2 —— 装饰者模式 

设计模式 3 —— 迭代器和组合模式(迭代器)

设计模式 4 —— 迭代器和组合模式(组合)

设计模式 5 —— 工厂模式

设计模式 6 —— 单件模式

设计模式 7 —— 命令模式

 

概述

第1部分 问题引入

第2部分 定义和实现

第3部分 使用宏命令

第1部分 问题引入

 首先看下,下面的要求:

bubuko.com,布布扣

实现命令接口

首先,让说有的命令对象实现相同的包含一个方法的接口。

1 /**
2  * 命令接口
3  * @ClassName: Command
4  * @author Xingle
5  * @date 2014-9-11 上午10:13:46
6  */
7 public interface Command {
8     public void execute();
9 }

 

实现一个打开电灯的命令

在实现打开电灯或者关闭电灯之前,先看下灯的类

 1 public class Light {
 2     
 3     public Light(){} 
 4     
 5     //开灯
 6     public void on(){
 7         System.out.println("Light is on");
 8     }
 9 
10     //关灯
11     public void off(){
12         System.out.println("Light is off");
13     }
14 }

 

接着开灯以及关灯命令:

 1 /**
 2  * 实现一个开灯命令
 3  * @ClassName: LightOnCommand
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 上午10:25:19
 7  */
 8 public class LightOnCommand implements Command{
 9     
10     Light light;
11     
12     public LightOnCommand(Light light){
13         this.light = light;
14     }
15 
16     @Override
17     public void execute() {
18         light.on();
19     }
20 
21 }

 

 1 /**
 2  * 实现一个关灯命令
 3  * @ClassName: LightOffCommand
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 上午10:55:35
 7  */
 8 public class LightOffCommand implements Command{
 9 
10     Light light;
11     
12     public LightOffCommand(Light light){
13         this.light = light;
14     };
15     
16     @Override
17     public void execute() {
18         light.off();        
19     }
20 
21 }

 

使用命令对象

假设我们有一个遥控器,它只有一个按钮和对应的插槽,可以控制一个装置:

 1 //
 2 //This is the invoker
 3 //
 4 public class SimpleRemoteControl {
 5     //一个插槽持有命令,控制着一个装置
 6     Command slot;
 7     
 8     public SimpleRemoteControl(){};
 9     
10     //这个方法用来设置插槽控制的命令。如果客户想要改变遥控器按钮的行为,可以多次调用这个方法
11     public void setCommand(Command command){
12         slot = command;
13     }
14     //当按下按钮时,这个方法就会被调用,使得当前命令衔接插槽,并调用它的execute()方法
15     public void buttonWasPressed(){
16         slot.execute();
17     }
18 }

 

下面再多加一个控制车库门的命令,车库门以及命令如下:

 1 /**
 2  * 车库门
 3  * @ClassName: GarageDoor 
 4  * @author Xingle
 5  * @date 2014-9-11 上午10:53:15
 6  */
 7 public class GarageDoor {
 8     public GarageDoor() {
 9     }
10 
11     public void up() {
12         System.out.println("Garage Door is Open");
13     }
14 
15     public void down() {
16         System.out.println("Garage Door is Closed");
17     }
18 
19     public void stop() {
20         System.out.println("Garage Door is Stopped");
21     }
22 
23     public void lightOn() {
24         System.out.println("Garage light is on");
25     }
26 
27     public void lightOff() {
28         System.out.println("Garage light is off");
29     }
30 }

 

 1 /**
 2  * 开车库门命令
 3  * @ClassName: GarageDoorOpenCommand
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 上午10:53:52
 7  */
 8 public class GarageDoorOpenCommand implements Command{
 9 
10     GarageDoor garageDoor;
11     
12     public GarageDoorOpenCommand(GarageDoor garageDoor) {
13         this.garageDoor = garageDoor;
14     }
15     
16     @Override
17     public void execute() {
18         garageDoor.up();
19     }
20 }

 

遥控器使用的简单测试:

 1 /**
 2  * 遥控器的测试程序
 3  * @ClassName: RemoteControlTest
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 上午10:57:38
 7  */
 8 public class RemoteControlTest {
 9     public static void main(String[] args){
10         //遥控器就是调用者,会传入一个命令对象,可以用来发出请求
11         SimpleRemoteControl remote = new SimpleRemoteControl();
12         
13         //创建了一个电灯对象,也就是请求的接受者
14         Light light = new Light();
15         GarageDoor garageDoor = new GarageDoor();
16         //创建一个命令,然后将接受者传给它
17         LightOnCommand lightOn = new LightOnCommand(light);
18         GarageDoorOpenCommand garageOpen = new GarageDoorOpenCommand(garageDoor);
19 
20         //把命令传给调用者
21         remote.setCommand(lightOn);
22         //模拟按下按钮
23         remote.buttonWasPressed();
24         
25         remote.setCommand(garageOpen);
26         remote.buttonWasPressed();
27     }
28 }

 

执行结果:

bubuko.com,布布扣

第2部分 定义和实现

命令模式 将“请求”封装成对象,以便使用不用的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

  一个命令对象通过在特定接受者上绑定一组动作来封装一个请求。要达到这一点,命令对象将动作和接受者包进对象中。这个对象只暴露一个execute() 方法,当此方法被调用的时候,接收者就会进行这些动作。从外面看,其他对象不知道究竟哪个接收者进行了哪些动作,只知道如果调用execute() 方法,请求的目的就能达到。

bubuko.com,布布扣

 

 

将命令指定到插槽

  将遥控器的每个插槽,对应到一个命令,这样就让遥控器变成“调用者”。当按下按钮,相应的命令对象的execute() 方法就会被调用,其结果是,接收者(例如:电灯、音响,电扇)的动作被调用。

bubuko.com,布布扣

 

实现遥控器

 1 /**
 2  * 带有撤销的遥控器
 3  * @ClassName: RemoteControlWithUndo 
 4  * @author Xingle
 5  * @date 2014-9-11 下午12:18:47
 6  */
 7 public class RemoteControlWithUndo {
 8 
 9     Command[] onCommands;
10     Command[] offCommands;
11     //前一个命令将被记录在这里
12     Command undoCommand;
13 
14     public RemoteControlWithUndo() {
15         //遥控器要处理7个开与关的命令,使用相应数组记录这些命令
16         onCommands = new Command[7];
17         offCommands = new Command[7];
18         //空对象
19         Command noCommand = new NoCommand();
20         
21         for (int i = 0; i < 7; i++) {
22             onCommands[i] = noCommand;
23             offCommands[i] = noCommand;
24         }
25         undoCommand = noCommand;
26     }
27 
28     public void setCommand(int slot, Command onCommand, Command offCommand) {
29         onCommands[slot] = onCommand;
30         offCommands[slot] = offCommand;
31     }
32 
33     public void onButtonWasPushed(int slot) {
34         onCommands[slot].execute();
35         undoCommand = onCommands[slot];
36     }
37 
38     public void offButtonWasPushed(int slot) {
39         offCommands[slot].execute();
40         undoCommand = offCommands[slot];
41     }
42 
43     public void undoButtonWasPushed() {
44         undoCommand.undo();
45     }
46 
47     public String toString() {
48         StringBuffer stringBuff = new StringBuffer();
49         stringBuff.append("\n------ Remote Control -------\n");
50         for (int i = 0; i < onCommands.length; i++) {
51             stringBuff.append("[slot " + i + "] "
52                     + onCommands[i].getClass().getName() + "    "
53                     + offCommands[i].getClass().getName() + "\n");
54         }
55         stringBuff.append("[undo] " + undoCommand.getClass().getName() + "\n");
56         return stringBuff.toString();
57     }
58 
59 }

 

命令接口

1 public interface Command {
2     
3     public void execute();
4     
5     //撤销操作
6     public void undo();
7 
8 }

 

灯 的类

 1 /**
 2  * 灯
 3  * @ClassName: Light
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 上午11:52:57
 7  */
 8 public class Light {
 9     String location = "";
10 
11     public Light(String location) {
12         this.location = location;
13     }
14 
15     public void on() {
16         System.out.println(location + " light is on");
17     }
18 
19     public void off() {
20         System.out.println(location + " light is off");
21     }
22 }

 

实现命令

 1 /**
 2  * 开灯
 3  * @ClassName: LightOnCommand
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 上午11:52:18
 7  */
 8 public class LightOnCommand implements Command{
 9     Light light ;
10 
11     public LightOnCommand(Light light){
12         this.light = light;
13     }
14     @Override
15     public void execute() {
16         light.on();
17     }
18     @Override
19     public void undo() {
20         light.off();
21     }
22 
23 }

 

 1 /**
 2  * 关灯
 3  * @ClassName: LightOffCommand 
 4  * @author Xingle
 5  * @date 2014-9-11 下午12:00:05
 6  */
 7 public class LightOffCommand implements Command {
 8 
 9     Light light;
10 
11     public LightOffCommand(Light light) {
12         this.light = light;
13     }
14 
15     @Override
16     public void execute() {
17         light.off();
18     }
19     
20     @Override
21     public void undo() {
22         light.on();
23     }
24 
25 }

 

音响

 1 /**
 2  * 音响
 3  * @ClassName: Stereo
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 上午11:54:46
 7  */
 8 public class Stereo {
 9     
10     String location;
11 
12     public Stereo(String location) {
13         this.location = location;
14     }
15 
16     public void on() {
17         System.out.println(location + " stereo is on");
18     }
19 
20     public void off() {
21         System.out.println(location + " stereo is off");
22     }
23 
24     public void setCD() {
25         System.out.println(location + " stereo is set for CD input");
26     }
27 
28     public void setDVD() {
29         System.out.println(location + " stereo is set for DVD input");
30     }
31 
32     public void setRadio() {
33         System.out.println(location + " stereo is set for Radio");
34     }
35 
36     public void setVolume(int volume) {
37         System.out.println(location + " Stereo volume set to " + volume);
38     }
39 
40 }

 

音响的命令操作

 1 /**
 2  * 开音响
 3  * @ClassName: StereoOnWithCDCommand
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 上午11:54:19
 7  */
 8 public class StereoOnWithCDCommand implements Command{
 9 
10     Stereo stereo;
11     
12     public StereoOnWithCDCommand(Stereo stereo) {
13         this.stereo = stereo;
14     }
15  
16     @Override
17     public void execute() {
18         stereo.on();
19     }
20 
21     @Override
22     public void undo() {
23         stereo.off();
24     }
25 
26 }

 

 1 /**
 2  * 关音响
 3  * @ClassName: StereoOffCommand
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 下午12:03:02
 7  */
 8 public class StereoOffCommand implements Command{
 9     Stereo stereo;
10     
11     public StereoOffCommand(Stereo stereo) {
12         this.stereo = stereo;
13     }
14 
15     @Override
16     public void execute() {
17         stereo.off();
18     }
19 
20     @Override
21     public void undo() {
22         stereo.on();
23     }
24 
25 }

 

吊扇

 1 /**
 2  * 吊扇
 3  * 
 4  * @ClassName: CeilingFan 
 5  * @author Xingle
 6  * @date 2014-9-11 下午12:36:04
 7  */
 8 public class CeilingFan {
 9 
10     
11     public static final int HIGH = 3;
12     public static final int MEDIUM = 2;
13     public static final int LOW = 1;
14     public static final int OFF = 0;
15     String location;
16     int speed;
17 
18     public CeilingFan(String location) {
19         this.location = location;
20         speed = OFF;
21     }
22 
23     //高速
24     public void high() {
25         speed = HIGH;
26         System.out.println(location + " ceiling fan is on high");
27     }
28     //中速
29     public void medium() {
30         speed = MEDIUM;
31         System.out.println(location + " ceiling fan is on medium");
32     }
33     //低速
34     public void low() {
35         speed = LOW;
36         System.out.println(location + " ceiling fan is on low");
37     }
38     //关闭
39     public void off() {
40         speed = OFF;
41         System.out.println(location + " ceiling fan is off");
42     }
43 
44     public int getSpeed() {
45         return speed;
46     }
47 
48 }

 

电扇的三个命令,分别把电扇开到高速,中速,和低速

 1 /**
 2  * 开电扇到高速
 3  * @ClassName: CeilingFanHighCommand 
 4  * @author Xingle
 5  * @date 2014-9-11 下午12:37:20
 6  */
 7 public class CeilingFanHighCommand implements Command {
 8 
 9     CeilingFan ceilingFan;
10     int prevSpeed;
11 
12     public CeilingFanHighCommand(CeilingFan ceilingFan) {
13         this.ceilingFan = ceilingFan;
14     }
15 
16     @Override
17     public void execute() {
18         prevSpeed = ceilingFan.getSpeed();
19         ceilingFan.high();
20     }
21 
22     @Override
23     public void undo() {
24         if (prevSpeed == CeilingFan.HIGH) {
25             ceilingFan.high();
26         } else if (prevSpeed == CeilingFan.MEDIUM) {
27             ceilingFan.medium();
28         } else if (prevSpeed == CeilingFan.LOW) {
29             ceilingFan.low();
30         } else if (prevSpeed == CeilingFan.OFF) {
31             ceilingFan.off();
32         }
33     }
34 
35 }

 

 1 /**
 2  * 开电扇到中速
 3  * @ClassName: CeilingFanMediumCommand
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 下午12:39:57
 7  */
 8 public class CeilingFanMediumCommand implements Command{
 9     CeilingFan ceilingFan;
10     int prevSpeed;
11 
12     public CeilingFanMediumCommand(CeilingFan ceilingFan) {
13         this.ceilingFan = ceilingFan;
14     }
15     @Override
16     public void execute() {
17         prevSpeed = ceilingFan.getSpeed();
18         ceilingFan.medium();
19     }
20 
21     @Override
22     public void undo() {
23         if (prevSpeed == CeilingFan.HIGH) {
24             ceilingFan.high();
25         } else if (prevSpeed == CeilingFan.MEDIUM) {
26             ceilingFan.medium();
27         } else if (prevSpeed == CeilingFan.LOW) {
28             ceilingFan.low();
29         } else if (prevSpeed == CeilingFan.OFF) {
30             ceilingFan.off();
31         }
32     }
33 }

 

 1 /**
 2  * 开电扇到低速
 3  * @ClassName: CeilingFanLowCommand
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 下午12:38:25
 7  */
 8 public class CeilingFanLowCommand implements Command{
 9     
10     CeilingFan ceilingFan;
11     int prevSpeed;
12   
13     public CeilingFanLowCommand(CeilingFan ceilingFan) {
14         this.ceilingFan = ceilingFan;
15     }
16 
17     @Override
18     public void execute() {
19         prevSpeed = ceilingFan.getSpeed();
20         ceilingFan.low();
21     }
22 
23     @Override
24     public void undo() {
25         if (prevSpeed == CeilingFan.HIGH) {
26             ceilingFan.high();
27         } else if (prevSpeed == CeilingFan.MEDIUM) {
28             ceilingFan.medium();
29         } else if (prevSpeed == CeilingFan.LOW) {
30             ceilingFan.low();
31         } else if (prevSpeed == CeilingFan.OFF) {
32             ceilingFan.off();
33         }
34     }
35 
36 }

 

关电扇命令

 1 /**
 2  * 关电扇
 3  * @ClassName: CeilingFanOffCommand
 4  * TODO
 5  * @author Xingle
 6  * @date 2014-9-11 下午12:45:18
 7  */
 8 public class CeilingFanOffCommand implements Command{
 9     
10     CeilingFan ceilingFan;
11     int prevSpeed;
12   
13     public CeilingFanOffCommand(CeilingFan ceilingFan) {
14         this.ceilingFan = ceilingFan;
15     }
16 
17     @Override
18     public void execute() {
19         prevSpeed = ceilingFan.getSpeed();
20         ceilingFan.off();
21     }
22 
23     @Override
24     public void undo() {
25         if (prevSpeed == CeilingFan.HIGH) {
26             ceilingFan.high();
27         } else if (prevSpeed == CeilingFan.MEDIUM) {
28             ceilingFan.medium();
29         } else if (prevSpeed == CeilingFan.LOW) {
30             ceilingFan.low();
31         } else if (prevSpeed == CeilingFan.OFF) {
32             ceilingFan.off();
33         }
34     }
35 
36 }

 

测试遥控器

 1 /**
 2  * 测试程序
 3  * 
 4  * @ClassName: RemoteLoader 
 5  * @author Xingle
 6  * @date 2014-9-11 上午11:57:26
 7  */
 8 public class RemoteLoader {
 9     public static void main(String[] args) {
10     
11         RemoteControlWithUndo remoteControl = new RemoteControlWithUndo();
12 
13         Light livingRoomLight = new Light("Living Room");
14 
15         CeilingFan ceilingFan = new CeilingFan("ww Room");
16         
17         
18         
19         LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
20         LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
21         
22         CeilingFanMediumCommand ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan);
23         CeilingFanLowCommand ceilingFanLow = new CeilingFanLowCommand(ceilingFan);
24         CeilingFanHighCommand ceilingFanHigh = new CeilingFanHighCommand(ceilingFan);
25         CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
26 
27         //
28         remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);        
29         remoteControl.setCommand(1, ceilingFanMedium, ceilingFanOff);
30         remoteControl.setCommand(2, ceilingFanHigh, ceilingFanOff);
31 
32         remoteControl.onButtonWasPushed(0);
33         remoteControl.offButtonWasPushed(0);
34         System.out.println(remoteControl);
35         remoteControl.undoButtonWasPushed();
36     
37         remoteControl.onButtonWasPushed(1);//中速开
38         remoteControl.offButtonWasPushed(1);//关闭
39         System.out.println(remoteControl);
40         remoteControl.undoButtonWasPushed();//撤销,会回到中速
41         
42         remoteControl.onButtonWasPushed(2);//高度开
43         System.out.println(remoteControl);//
44         remoteControl.undoButtonWasPushed();//撤销,回到中速
45     }
46 
47 }

 

执行结果:

Living Room light is on
Living Room light is off

------ Remote Control -------
[slot 0] firsthead.command.remote.LightOnCommand firsthead.command.remote.LightOffCommand
[slot 1] firsthead.command.remote.CeilingFanMediumCommand firsthead.command.remote.CeilingFanOffCommand
[slot 2] firsthead.command.remote.CeilingFanHighCommand firsthead.command.remote.CeilingFanOffCommand
[slot 3] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[slot 4] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[slot 5] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[slot 6] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[undo] firsthead.command.remote.LightOffCommand

Living Room light is on
ww Room ceiling fan is on medium
ww Room ceiling fan is off

------ Remote Control -------
[slot 0] firsthead.command.remote.LightOnCommand firsthead.command.remote.LightOffCommand
[slot 1] firsthead.command.remote.CeilingFanMediumCommand firsthead.command.remote.CeilingFanOffCommand
[slot 2] firsthead.command.remote.CeilingFanHighCommand firsthead.command.remote.CeilingFanOffCommand
[slot 3] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[slot 4] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[slot 5] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[slot 6] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[undo] firsthead.command.remote.CeilingFanOffCommand

ww Room ceiling fan is on medium
ww Room ceiling fan is on high

------ Remote Control -------
[slot 0] firsthead.command.remote.LightOnCommand firsthead.command.remote.LightOffCommand
[slot 1] firsthead.command.remote.CeilingFanMediumCommand firsthead.command.remote.CeilingFanOffCommand
[slot 2] firsthead.command.remote.CeilingFanHighCommand firsthead.command.remote.CeilingFanOffCommand
[slot 3] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[slot 4] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[slot 5] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[slot 6] firsthead.command.remote.NoCommand firsthead.command.remote.NoCommand
[undo] firsthead.command.remote.CeilingFanHighCommand

ww Room ceiling fan is on medium

 

第3部分 使用宏命令

 

设计模式 7 —— 命令模式

标签:style   blog   http   color   io   os   使用   ar   strong   

原文地址:http://www.cnblogs.com/xingele0917/p/3966326.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!