命令模式

(本文中一些例子和定义均摘自《Head First 设计模式》)
命令模式(Command Pattern)
将“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤消的操作。

举例:开灯的命令
首先我们定义一个命令接口,所有的命令都应当实现这个接口

public   interface  Command  {
    
public void execute();
}

 在Light类中,厂商定义了开和关的命令

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

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

}

接着我们需要把命令封装成对象

public   class  LightOnCommand  implements  Command  {
//开灯命令
    Light light;
    
    
public LightOnCommand(Light light){
        
this.light = light;
    }

    @Override
    
public void execute() {
        light.on();
    }

}


public   class  LightOffCommand  implements  Command  {
//关灯命令
    Light light;
    
public LightOffCommand(Light light){
        
this.light = light;
    }

    @Override
    
public void execute() {
        light.off();
    }


}

设定使用命令的方式

public   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();
        Light light 
= new Light();
        LightOnCommand lightOn 
= new LightOnCommand(light);
        
        remote.setCommand(lightOn);
        remote.buttonWasPressed();
        
        LightOffCommand lightOff 
= new LightOffCommand(light);
        remote.setCommand(lightOff);
        remote.buttonWasPressed();
    }


}

命令模式也可以用于撤消一系列的命令

我们应当记录下一系列的命令操作

public   class  RemoteControl  {
    
//记录开和关的命令
    Command[] onCommands;
    Command[] offCommands;
    
    
public RemoteControl() {
        onCommands 
= new Command[7];
        offCommands 
= new Command[7];
        
        Command noCommand 
= new NoCommand();
        
for(int i = 0; i < 7 ; i++{
            onCommands[i] 
= noCommand;
            offCommands[i] 
= noCommand;
        }

    }

    
    
public void setCommand(int slot, Command onCommand, Command offCommand){
        onCommands[slot] 
= onCommand;
        offCommands[slot] 
= offCommand;
    }

    
    
public void onButtonWasPushed(int slot) {
        onCommands[slot].execute();
    }

    
    
public void offButtonWasPushed(int slot) {
        offCommands[slot].execute();
    }

    
    
public String toString(){
        StringBuffer stringBuff 
= new StringBuffer();
        stringBuff.append(
" --------Remote Control------- ");
        
for(int i = 0; i < onCommands.length; i++{
            stringBuff.append(
"[slot" + i + "]" + onCommands[i].getClass().getName()
                    
+ "    " + offCommands[i].getClass().getName() + " ");
        }

        
return stringBuff.toString();
    }

}

在这里 发现每次设置命令都应当判断此处是否已经存在命令。但是每次都判断比较烦琐
所以:

public   class  NoCommand  implements  Command  {

    @Override
    
public void execute() {
        
// TODO Auto-generated method stub

    }


}

确保每个插槽都有一个命令对象。

然后需要给Command接口中加入撤消操作的方法

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

并且在所有具体的命令中实现这个方法。

public   class  LightOnCommand  implements  Command  {
    Light light;
    
    
public LightOnCommand(Light light){
        
this.light = light;
    }

    @Override
    
public void execute() {
        light.on();
    }

    
//灯开以前的操作是关闭
    public void undo() {
        light.off();
    }

}

重新设计一个控制台

public   class  RemoteControlWithUndo  {
    
//记录开和关的命令
    Command[] onCommands;
    Command[] offCommands;
    
//记录上一步的命令是什么
    Command undoCommand;
    
    
public RemoteControlWithUndo() {
        onCommands 
= new Command[7];
        offCommands 
= new Command[7];
        
        Command noCommand 
= new NoCommand();
        
for(int i = 0; i < 7 ; i++{
            onCommands[i] 
= noCommand;
            offCommands[i] 
= noCommand;
        }

        undoCommand 
= noCommand;
    }

    
    
public void setCommand(int slot, Command onCommand, Command offCommand){
        onCommands[slot] 
= onCommand;
        offCommands[slot] 
= offCommand;
    }

    
    
public void onButtonWasPushed(int slot) {
        onCommands[slot].execute();
        
//记录这一步的命令是来自哪个插槽
        undoCommand = onCommands[slot];
    }

    
    
public void offButtonWasPushed(int slot) {
        offCommands[slot].execute();
        
//记录这一步的命令是来自哪个插槽
        undoCommand = offCommands[slot];
    }

    
//按下undo的时候,执行undo方法
    public void undoButtonWasPushed() {
        undoCommand.undo();
    }

    
public String toString(){
        StringBuffer stringBuff 
= new StringBuffer();
        stringBuff.append(
" --------Remote Control------- ");
        
for(int i = 0; i < onCommands.length; i++{
            stringBuff.append(
"[slot" + i + "]" + onCommands[i].getClass().getName()
                    
+ "    " + offCommands[i].getClass().getName() + " ");
        }

        
return stringBuff.toString();
    }

}

测试一下undo

public   class  RemoteLoader  {

    
public static void main(String[] args) {
        RemoteControlWithUndo remoteControl 
= new RemoteControlWithUndo();
        
        Light livingRoomLight 
= new Light("Living Room");
        Light kitchenLight 
= new Light("Kitchen");
        
        LightOnCommand livingRoomLightOn 
= new LightOnCommand(livingRoomLight);
        LightOffCommand livingRoomLightOff 
= new LightOffCommand(livingRoomLight);
        
        LightOnCommand kitchenLightOn 
= new LightOnCommand(kitchenLight);
        LightOffCommand kitchenLightOff 
= new LightOffCommand(kitchenLight);
        
        
        remoteControl.setCommand(
0, livingRoomLightOn, livingRoomLightOff);
        remoteControl.setCommand(
1, kitchenLightOn, kitchenLightOff);
        
        System.out.println(remoteControl);
        
        remoteControl.onButtonWasPushed(
0);
        remoteControl.offButtonWasPushed(
0);
        
        remoteControl.undoButtonWasPushed();
        
        remoteControl.onButtonWasPushed(
1);
        remoteControl.offButtonWasPushed(
1);
        
        remoteControl.undoButtonWasPushed();
    }


}

这种模式更多的被应用在队列请求和日志中
比如当系统发生异常的时候,我们可以根据日志来要求事务的回滚,回到原先正常的状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值