笔记——命令模式

命令模式是将具体的一个或一组操作封装成一个独立命令的设计方法。
所有命令都实现同一个Command接口和其中的execute方法,调用者找到需要处理的命令并调用execute方法执行。

《HeadFirst设计模式》中提到的例子

智能家居电器厂商提供控制多种电器API,如电灯开关,风扇调速和开关,音响播放等,遥控器面板上有固定的按钮数,且每一排的可编程插槽上需要安装不同的装置来控制这些电器,应该如何设计遥控器的API?

笔记——命令模式_第1张图片

解决方法

考虑到电器的api是可变的,但遥控器样式相对固定,如果将每个按键的处理直接绑定api,耦合太高后续更新成本会变大。使用命令模式解决问题,遥控器的每一个按键功能在程序运行时才做绑定,保证扩展性。
笔记——命令模式_第2张图片

1.定义一个Command接口,包含一个execute方法

public interface Command {
    public void execute();
}

2.因为每种电器需要开和关2种操作,因此需要为每种电器定义2个实现了Command接口的类,分别对接开和关的操作。
如:

//开灯
public class LightOnCommand implements Command {
    private Light mLight;
    public LightOnCommand(Light l) {
        mLight = l;
    }

    @Override
    public void execute() {
        // TODO Auto-generated method stub
        mLight.on();
    }

}

//打开音响并自动播放
class StereoOnAndPlayCommand implements Command {
    private Stereo mStereo;

    public StereoOnAndPlayCommand(Stereo s) {
        mStereo = s;
    }

    @Override
    public void execute() {
        mStereo.on();
        mStereo.loadCD();
        mStereo.play();
    }

}

3.需要一个类作为中间者来管理命令,并提供按键的处理:

public class RemoteControl {

    private static final int SLOT_NUM = 7;
    Command[] mOnCommand;//保存各类电器的“打开”命令
    Command[] mOffCommand;//“关闭”命令

    public RemoteControl() {
        mOnCommand = new Command[SLOT_NUM];
        mOffCommand = new Command[SLOT_NUM];
    }

    //绑定每行on/off按键的Command
    public void setCommand(int slot, Command commandOn, Command commandOff){
        if(slot >= 0 && slot < SLOT_NUM){
            mOnCommand[slot] = commandOn;
            mOffCommand[slot] = commandOff;
        }
    }

    //提供按键处理
    public void buttonOnPressed(int slot){
        if(slot >= 0 && slot < SLOT_NUM)
        mOnCommand[slot].execute();
    }

    public void buttonOffPressed(int slot){
        if(slot >= 0 && slot < SLOT_NUM)
        mOffCommand[slot].execute();
    }

}

4.调用

public static void main(String[] args) {

        RemoteControl mRemote = new RemoteControl();
        //开灯{
        Light l = new Light();
        //绑定开和关的command
        mRemote.setCommand(0, new LightOnCommand(l), new LightOffCommand(l));
        mRemote.buttonOnPressed(0);
        //}
        //{打开音响
        Stereo s = new Stereo();
        mRemote.setCommand(1, new StereoOnAndPlayCommand(s), new StereoOffCommand(l));
        mRemote.buttonOnPressed(1);
        //}

    }

命令模式的优点:

将发出请求的对象和命令执行的对象解耦。

命令模式的其他应用:

  1. 队列请求
    将具体操作打包成一个命令,使用队列存储并批量处理这些命令。(可以应用线程池,Task等)
    处理方法从队列中读取一个请求,从队列中把它删除,然后执行请求的execute()。

  2. 日志请求
    为应对系统突发情况,应用可以将执行过的Command记录下来,一旦系统崩溃或重启可以有办法恢复到之前的状态。
    在Command接口中加入写日志和恢复的方法(store() & load()),在执行命令时会使用store方法将Command持久化写入log文件保存。load()方法即可以从log文件中恢复并执行Command,还原状态。

你可能感兴趣的:(设计模式)