• 设计模式:命令模式


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

      下面我们利用一个场景来进行理解理解

      场景:有一个遥控器,可以控制电灯、音响的开关,遥控器发出一个打开或关闭电灯或音响的请求,这个请求被我们封装成了命令对象。然后将命令对象传给接受者(即电灯或音响),接受者就可以执行命令了。

       下面我们就来看看代码的实现。首先我们先创建几个装置类对象

    //装置电灯
    public class Light {
        public void on(){
            System.out.println("Light ON");
        }
        
        public void off(){
            System.out.println("Light OFF");
        }
    }
    
    //装置音响
    public class Stereo {
        public void on(){
            System.out.println("Stereo ON");
        }
        
        public void off(){
            System.out.println("Stereo OFF");
        }
        
        public void setCD(){
            System.out.println("Stereo set a CD");
        }
        
        public void setVolume(){
            System.out.println("Stereo set volume 11");
        }
    }

      接着我们创建一个命令对象的接口,并创建各种装置的具体命令

    //创建一个命令对象的接口,所以命令都实现此接口
    public interface Command {
        //只需一个方法
        public void execute();
    }
    
    //命令对象--开灯命令
    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 StereoOnCommand implements Command {
        Stereo stereo;
        
        public StereoOnCommand(Stereo stereo){
            this.stereo = stereo;
        }
        @Override
        public void execute() {
            stereo.on();
            stereo.setCD();
            stereo.setVolume();
        }
    }
    
    //命令对象--关闭音响命令
    public class StereoOffCommand implements Command{
        Stereo stereo;
        
        public StereoOffCommand(Stereo stereo){
            this.stereo = stereo;
        }
        @Override
        public void execute() {
            stereo.off();
        }
    }

      当然,少不了遥控器对象了

    //遥控器对象
    public class RemoteControl {
        Command[] onCommands;
        Command[] offCommands;
            
        public RemoteControl(){
            onCommands = new Command[2];
            offCommands = new Command[2];
            
            Command noCommand = new NoCommand();
            for(int i=0; i<2; 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 class Test {
        public static void main(String[] args) {
            //创建一个遥控器
            RemoteControl remoteControl = new RemoteControl();
            
            //创建电灯、音响装置对象
            Light light = new Light();
            Stereo stereo = new Stereo();
            
            //创建所有装置的命令对象
            LightOnCommand lightOnCommand = new LightOnCommand(light);
            LightOffCommand lightOffCommand = new LightOffCommand(light);
            StereoOnCommand stereoOnCommand = new StereoOnCommand(stereo);
            StereoOffCommand stereoOffCommand = new StereoOffCommand(stereo);
            
            //将所有命令对象加载到遥控器中
            remoteControl.setCommand(0, lightOnCommand, lightOffCommand);
            remoteControl.setCommand(1, stereoOnCommand, stereoOffCommand);
            
            //下面进行开与关按钮测试
            remoteControl.onButtonWasPushed(0);
            remoteControl.OffButtonWasPushed(0);
            System.out.println("------");
            remoteControl.onButtonWasPushed(1);
            remoteControl.OffButtonWasPushed(1);
        }
    }

      运行结果如下:

      

      当然这里还没有撤销操作,其实撤销就是倒过来,我们现在稍微加下某些代码就可以实现了。

      首先在Command接口中添加撤销操作方法undo

    //创建一个命令对象的接口,所以命令都实现此接口
    public interface Command {
        //只需一个方法
        public void execute();
        public void undo();
    }

      接者在LightOnCommand中实现这个方法,因为开灯反过来就是添加light.off()方法

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

      同样道理,在其他命令对象中加入相应的undo。最后,我们在遥控器中加入一个撤销按钮

    //撤销按钮遥控器对象
    public class RemoteControlWithUndo {
        Command[] onCommands;
        Command[] offCommands;
        //撤销前一个命令对记录在这个对象中
        Command undoCommand;
            
        public RemoteControlWithUndo(){
            onCommands = new Command[2];
            offCommands = new Command[2];
            
            Command noCommand = new NoCommand();
            for(int i=0; i<2; 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];
        }
        //调用撤销按钮
        public void undoButtonWasPushed(){
            undoCommand.undo();
        }
    }

      最后测试下撤销操作。

    public class Test {
        public static void main(String[] args) {
            //创建一个遥控器
            RemoteControlWithUndo remoteControl = new RemoteControlWithUndo();
            
            //创建电灯、音响装置对象
            Light light = new Light();
            Stereo stereo = new Stereo();
            
            //创建所有装置的命令对象
            LightOnCommand lightOnCommand = new LightOnCommand(light);
            LightOffCommand lightOffCommand = new LightOffCommand(light);
            StereoOnCommand stereoOnCommand = new StereoOnCommand(stereo);
            StereoOffCommand stereoOffCommand = new StereoOffCommand(stereo);
            
            //将所有命令对象加载到遥控器中
            remoteControl.setCommand(0, lightOnCommand, lightOffCommand);
            remoteControl.setCommand(1, stereoOnCommand, stereoOffCommand);
            
            //下面进行开与关按钮测试
            remoteControl.onButtonWasPushed(0);
            remoteControl.offButtonWasPushed(0);
            System.out.println("---撤销关闭电灯---");
            remoteControl.undoButtonWasPushed();
            System.out.println();
            
            remoteControl.onButtonWasPushed(1);
            System.out.println("---撤销打开音响---");
            remoteControl.onButtonWasPushed(1);
        }
    }

      运行结果如下:

          

      好了,这就是一个简单的命令模式了,重点在于将“请求”封装成对象。然后将这对象进行传输。

      

      下一节:适配器模式

    作者:哀&RT
    出处:博客园哀&RT的技术博客--http://www.cnblogs.com/Tony-Anne/
    您的支持是对博主最大的鼓励,感谢您的认真阅读。
    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    机器学习进度(六)—— 主成分分析
    留言版
    打赏
    第十四周总结
    第十三周总结
    软件测试读后感(二)
    第十二周总结
    第十一周总结
    软件测试读后感(一)
    虚拟机常用shell命令
  • 原文地址:https://www.cnblogs.com/Tony-Anne/p/6510703.html
Copyright © 2020-2023  润新知