设计模式(七)学习----命令模式

命令模式的定义

模式的组成:

* 抽象命令类(Command):声明执行操作的接口。调用接收者TVReceiver响应的操作,以实现执行的方法execute。
* 具体命令类(TvChangeCommand,TvCloseCommand,TvOpenCommand):创建一个具体命令对象并设定它的接收者。通常会持有接收者,并调用接收者的功能来完成命令要执行的操作
* 调用者(RemoteControllerInvoke 遥控器调用类,请求的发送者):要求该命令执行这个请求,通常会持有命令对象,可以持有很多的命令对象。
* 接收者(TVReceiver 电视机,请求的接收者): 知道如何实施和执行一个请求相关的操作。任何类都可能作为一个接收者,只要它能够实现命令要求实现的功能。
* 客户端(ConmandClient):创建具体的命令对象,并且创建设置命令的接收者。真正的使用命令客户端是从RemoteControllerInvoke来触发执行的。

形象的类比:
电视机遥控器 :
电视机是请求的接收者,
遥控器是请求的发送者,
遥控器上有一些按钮,不同的按钮对应电视机的不同操作。抽象命令角色由一个命令接口来扮演,
有三个具体的命令类实现了抽象命令接口,这三个具体命令类分别代表三种操作:打开电视机、关闭电视机和切换频道。
显然,电视机遥控器就是一个典型的命令模式应用实例。

1.声明执行操作的接口,抽象命令类:

public interface Command {

    /**
     * 执行命令的方法
     */
    void execute();
}

2.具体命令类:

package desigh.commands.commands;

/**
 * 具体电视关闭的命令
 *
 * @author lipeng24@meituan.com
 * @create 2017-10-18 下午2:39
 **/

public class TvChangeCommand implements Command {
    private TVReceiver tvReceiver;

    /**
     * 构造方法,传入响应的接收对象
     *
     * @param receiver
     */
    public TvChangeCommand(TVReceiver receiver) {
        this.tvReceiver = receiver;
    }

    /**
     * 具体的执行的方法
     */
    @Override
    public void execute() {
        tvReceiver.changeTV();
    }
}
package desigh.commands.commands;

/**
 * 具体电视关闭的命令
 *
 * @author lipeng24@meituan.com
 * @create 2017-10-18 下午2:39
 **/

public class TvCloseCommand implements Command {
    private TVReceiver tvReceiver;

    /**
     * 构造方法,传入响应的接收对象
     *
     * @param receiver
     */
    public TvCloseCommand(TVReceiver receiver) {
        this.tvReceiver = receiver;
    }

    /**
     * 具体的执行的方法
     */
    @Override
    public void execute() {
        tvReceiver.closeTV();
    }
}
package desigh.commands.commands;

/**
 * 具体电视打开的命令
 *
 * @author lipeng24@meituan.com
 * @create 2017-10-18 下午2:39
 **/

public class TvOpenCommand implements Command {
    private TVReceiver tvReceiver;

    /**
     * 构造方法,传入响应的接收对象
     *
     * @param receiver
     */
    public TvOpenCommand(TVReceiver receiver) {
        this.tvReceiver = receiver;
    }

    /**
     * 具体的执行的方法
     */
    @Override
    public void execute() {
        tvReceiver.openTV();
    }
}
3.具体命令类接收者类:
package desigh.commands.commands;

/**
 * 电视机接收命令   receiver
 *
 * @author lipeng24@meituan.com
 * @create 2017-10-18 下午12:37
 **/

public class TVReceiver {

    /**
     * 真正执行命令
     */
    public void openTV() {
        System.out.println("open TV ");
    }

    /**
     * 关闭电视
     */
    public void closeTV() {
        System.out.println("close TV ");
    }

    /**
     * 电视换台
     */
    public void changeTV() {
        System.out.println("change TV menu");
    }


}

4.遥控器调用者类

package desigh.commands.commands;

import java.util.ArrayList;
import java.util.List;

/**
 * 遥控器调用类
 *
 *
 *
 * @author lipeng24@meituan.com
 * @create 2017-10-18 下午2:49
 **/

public class RemoteControllerInvoke {
    private List<Command> commands = new ArrayList<>();

    /**
     *
     * @param cmd
     */
    public void operateTvCommand(Command cmd) {
        this.commands.add(cmd);
        System.out.println(commands);
        cmd.execute();
    }
}
5 客户端
package desigh.commands.commands;

/**
 * 入口client
 *
 * @author lipeng24@meituan.com
 * @create 2017-10-18 下午2:56
 **/

public class ConmandClient {

    /**
     * 输出结果:
     * open TV
     * change TV menu
     * close TV
     *
     * @param args
     */
    public static void main(String[] args) {
        // 这里还可以抽象一层,不同的电器除了电视机还有空调,灯等电器
        TVReceiver receiver = new TVReceiver();
        Command openCommand = new TvOpenCommand(receiver);
        Command closeCommand = new TvCloseCommand(receiver);
        Command changeCommand = new TvChangeCommand(receiver);
        RemoteControllerInvoke remoteControllerInvoke = new RemoteControllerInvoke();

        //remoteControllerInvoke 遥控器遥控遥控器上面的命令,电视机接收3个命令之后执行方法
        remoteControllerInvoke.operateTvCommand(openCommand);
        remoteControllerInvoke.operateTvCommand(changeCommand);
        remoteControllerInvoke.operateTvCommand(closeCommand);

    }
}

命令模式的优点:
 * 1.降低系统的耦合度:将调用操作的对象与知道如何实现该操作的对象解耦
* 2.组合命令:可以将多个命令分配成一个组合命令,可以比较容易的设计一个命令队列和宏命令。
* 3.符合开闭原则:增加新的具体的Command很容易,无需改变现有的类
* 4.可以方便的实现对请求或者说命令的Undo撤销和Redo恢复

缺点:
导致某些系统有过多的具体命令类。5 命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。

参考
http://blog.csdn.net/hguisu/article/details/7549895
https://foolchild.cn/2016/07/26/command
https://en.wikipedia.org/wiki/Command_patter
执行框架:LogicUnitExecutor(invoker),LogicUnitQueueGroup(command)