• 命令模式


    一 定义

    命令模式也属于行为型设计模式之一。
    定义:将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。

    所以,命令模式的本质是,封装请求。

    二 模式结构

     
     

    角色介绍

    • Receiver:接收者角色。
      该类是命令的具体执行者,负责具体实施或者执行一个请求,说的通俗一点,就是真正干活的角色。
    • Command:命令角色
      定义所有的具体命令类的抽象接口。
    • ConcreteCommand:具体命令角色
      该类实现了Command接口
    • Invoker:请求者角色
      该类的职责是调用命令对象执行具体的请求。
    • Client:客户端

    通用代码如下

    • 抽象的命令接口
    public interface Command {
    
        /**
         * 执行具体操作的命令
         */
        void execute();
    }
    
    • 接收者类
    public class Receiver {
    
        /**
         * 真正执行具体命令逻辑的方法
         */
        public void action(){
            System.out.println("执行具体的操作");
        }
    }
    
    • 具体的命令类
    public class ConcreteCommand implements Command{
    
        private Receiver mReceiver;
    
        public ConcreteCommand(Receiver receiver){
            this.mReceiver=receiver;
        }
    
    
        @Override
        public void execute() {
            // 调用接收者的相关方法来执行具体逻辑
            mReceiver.action();
        }
    }
    
    • 请求者类
    public class Invoker {
    
        private Command mCommand; // 持有一个对应命令对象的引用
    
        public Invoker(Command command){
            this.mCommand=command;
        }
    
        public void action(){
            // 调用具体命令对象的相关方法,执行具体命令
            mCommand.execute();
        }
    
    }
    
    • 客户端测试代码
            // 构造一个接收者对象
            Receiver receiver=new Receiver();
            // 根据接收者对象构造一个命令对象
            Command command=new ConcreteCommand(receiver);
            // 根据具体的对象构造请求者对象
            Invoker invoker=new Invoker(command);
            // 执行请求方法
            invoker.action();
    

    三 实例

    我们以遥控器遥控电视为例,以前的电视是没有遥控器的,你如果想换台的话,要跑到电视机前,手动按换台按键,非常麻烦。现在我们有了遥控器,如果想换台,按一下遥控器的换台按键,就可以实现换台。在这里,我们是通过遥控器发出的命令,所以遥控器相当于Invoker,命令发出者,我们相当于客户端,我们的责任是组装遥控器。遥控器上的每个具体按键,都是一个具体的命令。通过遥控器,就实现了我们和电视机之间的解耦。

    • Receiver角色
      Receiver是命令的具体执行者,我们在这里实现了四个命令逻辑,分别是,节目加,节目减,音量加,音量减。
    /*
     * Receiver角色,真正的命令执行者
     * @author Jackson
     * @version 1.0.0
     * since 2019 05 09
     */
    public class ChangeReceiver {
    
        /**
         * 真正处理节目加的逻辑
         */
         public void addItem(){
             System.out.println("节目+");
         }
    
    
        /**
         * 真正处理节目减的逻辑
         */
        public void subtractItem(){
             System.out.println("节目-");
         }
    
    
        /**
         * 真正处理音量加的逻辑
         */
        public void addVoice(){
            System.out.println("音量+");
        }
    
        /**
         * 真正处理音量减的逻辑
         */
        public void subtractVoice(){
            System.out.println("音量-");
        }
        
    }
    
    • 命令接口
    public interface Command {
    
       /**
        * 执行具体操作的命令
        */
       void execute();
    
    }
    
    • 具体的命令
      分别是节目加,节目减,音量加,音量减四个具体命令。
    public class AddItemCommand implements Command{
    
        // 持有一个接收者对象的引用
        private ChangeReceiver mChangeReceiver;
    
        public AddItemCommand(ChangeReceiver changeReceiver){
            this.mChangeReceiver=changeReceiver;
        }
    
    
    
        @Override
        public void execute() {
            // 调用遥控器的具体方法执行操作
            mChangeReceiver.addItem();
        }
    }
    
    public class SubtractItemCommand implements Command{
    
        // 持有一个接收者对象的引用
        private ChangeReceiver mChangeReceiver;
    
        public SubtractItemCommand(ChangeReceiver changeReceiver){
            this.mChangeReceiver=changeReceiver;
        }
    
    
        @Override
        public void execute() {
            // 调用遥控器的具体方法执行操作
            mChangeReceiver.subtractItem();
        }
    }
    
    public class AddVoiceCommand implements Command{
    
        // 持有一个接收者对象的引用
        private ChangeReceiver mChangeReceiver;
    
        public AddVoiceCommand(ChangeReceiver changeReceiver){
            this.mChangeReceiver=changeReceiver;
        }
    
        @Override
        public void execute() {
            // 调用遥控器的具体方法执行操作
            mChangeReceiver.addVoice();
        }
    }
    
    public class SubtractVoiceCommand implements Command{
    
        // 持有一个接收者对象的引用
        private ChangeReceiver mChangeReceiver;
    
    
        public SubtractVoiceCommand(ChangeReceiver changeReceiver){
            this.mChangeReceiver=changeReceiver;
        }
    
        @Override
        public void execute() {
            // 调用遥控器的具体方法执行操作
            mChangeReceiver.subtractVoice();
        }
    }
    
    
    • 组装遥控器
      把四个命令按键安装到遥控器上,相当于Invoker,请求者角色。
    public class RemoteControler {
    
        private AddItemCommand mAddItemCommand;       // 节目加命令对象的引用
        private SubtractItemCommand mSubtractItemCommand;  // 节目减命令的引用
        private AddVoiceCommand mAddVoiceCommand;         // 声音加命令的引用
        private SubtractVoiceCommand mSubtractVoiceCommand;  // 声音减命令的引用
        
    
        public void setAddItemCommand(AddItemCommand addItemCommand) {
            mAddItemCommand = addItemCommand;
        }
        
    
        public void setSubtractItemCommand(SubtractItemCommand subtractItemCommand) {
            mSubtractItemCommand = subtractItemCommand;
        }
        
        public void setAddVoiceCommand(AddVoiceCommand addVoiceCommand) {
            mAddVoiceCommand = addVoiceCommand;
        }
    
    
        public void setSubtractVoiceCommand(SubtractVoiceCommand subtractVoiceCommand) {
            mSubtractVoiceCommand = subtractVoiceCommand;
        }
    
    
        /**
         * 遥控器上的节目加按键
         */
        public void addItem(){
            mAddItemCommand.execute();
        }
    
    
        /**
         * 遥控器上的节目减按键
         */
        public void subtractItem(){
            mSubtractItemCommand.execute();
        }
    
    
        /**
         * 遥控器上的声音加按键
         */
        public void addVoice(){
            mAddVoiceCommand.execute();
        }
    
        /**
         * 遥控器上的声音减按键
         */
        public void subtractVoice(){
            mSubtractVoiceCommand.execute();
        }
    
        
    }
    
    • 客户端代码
     // 首先要有一个接收者对象
            ChangeReceiver changeReceiver=new ChangeReceiver();
            // 构造四个命令
            AddItemCommand addItemCommand=new AddItemCommand(changeReceiver);
            SubtractItemCommand subtractItemCommand=new SubtractItemCommand(changeReceiver);
            AddVoiceCommand addVoiceCommand=new AddVoiceCommand(changeReceiver);
            SubtractVoiceCommand subtractVoiceCommand=new SubtractVoiceCommand(changeReceiver);
    
            // 组装遥控器,把代表不同命令的按键组装到遥控器上
            RemoteControler remoteControler=new RemoteControler();
            remoteControler.setAddItemCommand(addItemCommand);
            remoteControler.setSubtractItemCommand(subtractItemCommand);
            remoteControler.setAddVoiceCommand(addVoiceCommand);
            remoteControler.setSubtractVoiceCommand(subtractVoiceCommand);
    
            // 我们可以愉快地通过遥控器对电视发出遥控指令了
            remoteControler.addItem();
            remoteControler.subtractItem();
            remoteControler.addVoice();
            remoteControler.subtractVoice();
    

    四 优缺点

    优点

    • 类间解耦
      请求者与接收者之间没有任何依赖关系,请求者实现功能只需调用Command中的execute方法即可,不需要了解底层是哪个接收者。
    • 可扩展性
      Command具体的类可以非常容易扩展。

    缺点
    如果Command比较多,会造成类数目的膨胀。所以在实际开发中要不要采用命令模式还需要斟酌。


    作者:Jackson杰
    转自链接:https://www.jianshu.com/p/aa3e2fbe503b
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 相关阅读:
    telnet和ssh
    sersync实现实时同步
    rsync服务端一键安装rsync脚本(源码)
    rsync客户端一键安装rsync脚本(源码)
    rsync客户端一键安装rsync脚本(非源码)
    centos 建立Clamav自动扫描脚本
    DELL T110II Server如何通过RAID 级别迁移的方式在OMSA下实现磁盘阵列扩容?
    Dell PowerEdgeServerT110II USB Boot更新
    Centos7最小安装下Install Clamav(2017-06-09最后更新)
    Centos7 samba 匿名共享 简单config
  • 原文地址:https://www.cnblogs.com/xifenglou/p/11394979.html
Copyright © 2020-2023  润新知