命令模式
来源:互联网 发布:java 设置语言环境 编辑:程序博客网 时间:2024/05/26 17:46
命令模式将请求封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
现在有如下图遥控器。有3个可编程的插槽,以及对应的按钮。黑色按钮为开关按钮,有按下和弹起,两种状态。红色按钮为撤销按钮,撤销上一次操作,只有一种状态,按下立即弹起。
现在有两个电器。
// 电灯对象public class Light { public void on(){ System.out.println("light on ..."); } public void off(){ System.out.println("light off ..."); }}// 音响对象public class Stereo { private String name; private int volume; public void on() { System.out.println("stereo on ..."); } public void off() { System.out.println("stereo off ..."); } public void insertCD(String name) { this.name = name; System.out.println("CD " + name + " insert ..."); } public void takeCD() { this.name = ""; System.out.println("CD " + name + " take ..."); } public void setVolume(int volume) { this.volume = volume; System.out.println("volume set " + volume); }}
类图
我们通过编程来让遥控器控制电器。
// 命令接口public interface Command { void execute(); void undo();}// 空命令public class NoCommand implements Command { @Override public void execute() { System.out.println("command is null"); } @Override public void undo() { System.out.println("command is null"); }}// 开启电灯命令public class LightOn implements Command { private Light light; public LightOn(Light light) { this.light = light; } @Override public void execute() { light.on(); } @Override public void undo() { light.off(); }}// 电灯关闭命令public class LightOff implements Command { private Light light; public LightOff(Light light) { this.light = light; } @Override public void execute() { light.off(); } @Override public void undo() { light.on(); }}// 打开音响命令public class StereoOn implements Command { private Stereo stereo; public StereoOn(Stereo stereo) { this.stereo = stereo; } @Override public void execute() { stereo.on(); stereo.insertCD("XXX CD"); stereo.setVolume(10); } @Override public void undo() { stereo.setVolume(0); stereo.takeCD(); stereo.off(); }}// 关闭音响命令public class StereoOff implements Command { private Stereo stereo; public StereoOff(Stereo stereo) { this.stereo = stereo; } @Override public void execute() { stereo.setVolume(0); stereo.takeCD(); stereo.off(); } @Override public void undo() { stereo.on(); stereo.insertCD("XXX CD"); stereo.setVolume(10); }}// 宏命令public class Macro implements Command { private List<Command> list; public Macro(List<Command> list) { this.list = list; } @Override public void execute() { for (Command command : list) { command.execute(); } } @Override public void undo() { for (Command command : list) { command.undo(); } }}// 遥控器public class RemoteControl { // 遥控器上插槽的数量 private int num = 3; private Command[] onCommands; private Command[] offCommands; private Stack<Command> historyCommands; public RemoteControl() { onCommands = new Command[num]; offCommands = new Command[num]; historyCommands = new Stack<>(); Command noCommand = new NoCommand(); // 所有插槽初始化为同一个空对象 for (int i = 0; i < num; i++) { onCommands[i] = noCommand; offCommands[i] = noCommand; } } public void setCommand(int slot, Command onCommand, Command offCommand) { if (slot < num && slot > -1) { onCommands[slot] = onCommand; offCommands[slot] = offCommand; } else { throw new ArrayIndexOutOfBoundsException("slot is not exist"); } } // 按下按钮 public void buttonDown(int slot) { if (slot < num && slot > -1) { onCommands[slot].execute(); historyCommands.push(onCommands[slot]); } else { throw new ArrayIndexOutOfBoundsException("slot is not exist"); } } // 按钮弹起 public void buttonUp(int slot) { if (slot < num && slot > -1) { offCommands[slot].execute(); historyCommands.push(offCommands[slot]); } else { throw new ArrayIndexOutOfBoundsException("slot is not exist"); } } // 撤销按钮 public void undo() { if (historyCommands.isEmpty()) { System.out.println("do not have history command"); } else { historyCommands.pop().undo(); } }}// 测试类public class Test { public static void main(String[] args) { new Test().test(); } private void test() { // 遥控器对象 RemoteControl remoteControl = new RemoteControl(); // 各种家电 Light light = new Light(); Stereo stereo = new Stereo(); // 命令 LightOn lightOn = new LightOn(light); LightOff lightOff = new LightOff(light); StereoOn stereoOn = new StereoOn(stereo); StereoOff stereoOff = new StereoOff(stereo); // 宏命令 List<Command> onCommands = new ArrayList() { { add(lightOn); add(stereoOn); } }; Macro macroOn = new Macro(onCommands); List<Command> offCommands = new ArrayList() { { add(lightOff); add(stereoOff); } }; Macro macroOff = new Macro(offCommands); // 插入命令 remoteControl.setCommand(0, lightOn, lightOff); remoteControl.setCommand(1, stereoOn, stereoOff); remoteControl.setCommand(2, macroOn, macroOff); // 操作遥控器 remoteControl.buttonDown(0); remoteControl.buttonUp(0); remoteControl.buttonDown(1); remoteControl.buttonUp(1); remoteControl.buttonDown(2); remoteControl.buttonUp(2); System.out.println(11111); remoteControl.undo(); remoteControl.undo(); remoteControl.undo(); }}
注:
- 我们把所有的电器的操作封装,暴露execute和undo方法。现在遥控器可以很方便的统一操作各种电器。
- 将发出请求的对象和接受请求的对象解耦
- 可以用来实现队列、日志、事务等
- 队列:一个线程负责把命令封装放入对序列中,另一个线程从队列中取出命令,调用execute方法
- 日志:把每次的操作记录下来,出现异常时读取日志,重新执行被记录的操作
参考文章
1. Head First 设计模式
0 0
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- SQLServer出现连接异常
- Android中的各种访问权限Permission含义
- spark厦大----基本的统计工具(1)
- HANA基本概念
- 多层json文件解析list取值。
- 命令模式
- mybatis做like模糊查询
- My97DatePicker 日期控制,开始时间不能大于结束时间,结束时间不能小于开始时间
- shader实例溶解,燃烧效果
- ubuntu下安装arm-linux-gcc交叉编译链
- [剑指offer]Fibonacci数列
- 组件方式开发 Web App全站-8-总项目
- quartz scheduler 2.16 之集群
- 架设自己的NuGet服务器