zoukankan      html  css  js  c++  java
  • 设计模式(七)学习----命令模式

    命令模式的定义

    模式的组成:

    * 抽象命令类(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恢复

    缺点:
    导致某些系统有过多的具体命令类。

    总结与分析:

    1 命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。
    2 每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作
    3 命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
    4 命令模式使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。
    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)
  • 相关阅读:
    49个128*128像素的天气png图标
    非常漂亮的千千静听皮肤[Warp]出自梦梦的作品
    腾讯的面试题
    什么是函数参数,如何传递函数参数
    我看了这视频,情不自禁的笑了
    WindowBlinds基础使用教程
    晒工资网站
    一个可以搜索word文档,电子表格,PDF,幻灯片的搜索引擎
    网页设计常用png小图标一套
    使用U盘时候的”无法停用通用卷”的解决办法
  • 原文地址:https://www.cnblogs.com/200911/p/8182607.html
Copyright © 2011-2022 走看看