命令模式
来源:互联网 发布:java输出2到200的素数 编辑:程序博客网 时间:2024/06/05 14:17
在我们编程应用中或者生活之中。我们希望用一个统一的遥控器,这个遥控器可以对家电进行统一的off和on操作,但是这些遥控器却不需要知道这些家电自动化的细节。
命令模式可以将“动作的请求者”从“动作的执行者”对象中解耦。请求者为遥控器,执行者为家电。
做法是把请求封装成一个特定的对象(如电灯对象)。所以如果对每个按钮都存储一个命令对象,那么当按下按钮的时候,就可以请命令对象做相关的工作。遥控器并不需要知道工作内容是什么,只要有个命令对象能和正确的对象沟通,把事情做好就行了。这样便实现了请求者与执行者之间的解耦。
首先我们要编写统一的命令接口
public interface Command { public void execute();}然后创建一个电灯,该电灯有关闭和打开的操作。
class Light{ public void on(){ System.out.println("打开电灯"); } public void off(){ System.out.println("关闭电灯"); }}原始的操作是让命令的调用者持有该灯操作如下
public class SimpleRemoteControl { public void lightControl(String type){ Light light=new Light(); if(type.equals("off")) light.off(); else light.on(); }}
这样会造成请求者与执行者之间的耦合。如果该电灯还有调节灯光强弱的功能的话,我们就要对该对象中的方法进行修改,这样违反了设计原则“对修改关闭,对扩展开发”。
命令模式将这种控制提出,封装成对象。
class LightOnCommand implements Command{ Light light; @Override public void execute() { // TODO Auto-generated method stub light.on(); } public LightOnCommand(Light light){ this.light=light; }}class LightOffCommand implements Command{ Light light; @Override public void execute() { // TODO Auto-generated method stub light.off(); } public LightOffCommand(Light light){ this.light=light; }}这样,请求者只需要知道调用该命令对某家电控制,但是不知道该控制的细节,实现了请求者与执行者之间的解耦。
public class SimpleRemoteControl { Command slot; public SimpleRemoteControl(){ } public void setCommand(Command command){ slot=command; } public void buttonWasPressed(){ slot.execute(); }}但是我们并不想一个操作对应一个遥控器,我们想用一个遥控器对所有家电进行统一的管理。这样我们可以在SimpleRemoteControl类中的成员变量Command设置成数组,来进行统一的管理,代码如下:
public class SimpleRemoteControl { Command[] onCommands;//统一的开按钮命令 Command[] offCommands;//统一的关按钮命令 public SimpleRemoteControl(){ onCommands=new Command[7]; offCommands=new Command[7]; for(int i=0;i<7;i++){ onCommands[i]=new NoCommand(); offCommands[i]=new NoCommand(); } } public void setCommand(int slot,Command onCommand,Command offCommand){ onCommands[slot]=onCommand; offCommands[slot]=offCommand; } public void buttonWasPressed(int slot){ onCommands[slot].execute(); } public void buttonWasOff(int slot){ offCommands[slot].execute(); }}其中NoCommand为一个实现Command接口的空类,这样做的目的是可以省去在按钮按下判断按钮是否为空的操作。
class NoCommand implements Command{ @Override public void execute() { // TODO Auto-generated method stub System.out.println("该按钮无效"); }}该模式还能扩展,提供撤销功能。我们生活中比如电视遥控器,经常想回到上一个看的频道,这样我们需要撤销当前操作。在编程中,其实我们只需要记录上一个操作是什么即可。如果我们想撤销多个命令,就要将该记录上一个操作的变量定义为一个堆栈,用堆栈来存储每次新操作的命令,撤销只需要将该命令从堆栈中移除。当然Command接口也要新添加undo撤销方法,并让子类实现该方法。
public interface Command { public void execute(); public void undo();//撤销命令}class NoCommand implements Command{ @Override public void execute() { // TODO Auto-generated method stub System.out.println("该按钮无效"); } @Override public void undo() { // TODO Auto-generated method stub }}class LightOnCommand implements Command{ Light light; @Override public void execute() { // TODO Auto-generated method stub light.on(); } public LightOnCommand(Light light){ this.light=light; } @Override public void undo() { // TODO Auto-generated method stub light.off(); }}class LightOffCommand implements Command{ Light light; @Override public void execute() { // TODO Auto-generated method stub light.off(); } public LightOffCommand(Light light){ this.light=light; } @Override public void undo() { // TODO Auto-generated method stub light.on(); }}public class SimpleRemoteControl { Command[] onCommands; Command[] offCommands; Stack<Command> stack;//撤销栈,来存储命令记录 public SimpleRemoteControl(){ onCommands=new Command[7]; offCommands=new Command[7]; for(int i=0;i<7;i++){ onCommands[i]=new NoCommand(); offCommands[i]=new NoCommand(); } stack=new Stack<>(); } public void setCommand(int slot,Command onCommand,Command offCommand){ onCommands[slot]=onCommand; offCommands[slot]=offCommand; } public void buttonWasPressed(int slot){ onCommands[slot].execute(); stack.push(onCommands[slot]); } public void buttonWasOff(int slot){ offCommands[slot].execute(); stack.push(offCommands[slot]); } public void undoButton(){ if(!stack.isEmpty()) { System.out.print("撤销命令:"); stack.peek().execute(); System.out.print("执行:"); stack.pop().undo(); } }}main方法
public static void main(String[] args) { // TODO Auto-generated method stub SimpleRemoteControl remoteControl=new SimpleRemoteControl(); Light living=new Light(); LightOnCommand lightOnCommand=new LightOnCommand(living); LightOffCommand lightOffCommand=new LightOffCommand(living); remoteControl.setCommand(0, lightOnCommand, lightOffCommand); remoteControl.buttonWasPressed(0); remoteControl.buttonWasOff(0); System.out.println("撤销命令1:"); remoteControl.undoButton(); System.out.println("撤销命令2:"); remoteControl.undoButton(); }
命令模式:将请求封装成对象,这可以让你使用不同的请求、队列或者日志请求来参数化其他对象。命令模式也可以支持撤销操作。
命令模式降低了系统的耦合度,同时可以很容易的让新的命令添加进去,不用对原对象进行修改。
但是命令模式可能会导致系统过多的命令类。因为每一个命令都要实现Command接口生成新的类。
使用场景为
1.系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
2.系统需要在不同的时间指定请求、将请求排队和执行请求。
3.系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
4.系统需要将一组操作组合在一起,即支持宏命令。
以上是自己的浅见,不喜勿喷哈。有错误希望指正。
1 0
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- 命令模式
- js 控制台输出
- input框的placeholder使用line-height在Safari上不垂直居中的问题
- 【杭电】[1312]Red and Black
- 机器学习面试问题5
- 纯js css3 实现loading demo
- 命令模式
- Maven工程自动化构建方法
- day2:gnuradio 实现fm发射机
- 浅析Java虚拟机结构与机制
- 牛客网在线编程题规范实例
- Oracle 用一个表字段更新另一个表字段三种方法
- Redis命令-详细
- 解决Android中No resource found that matches android:TextAppearance.Material.Widget.Button.Inverse问题
- ny 58 最少步数(bfs)