美文网首页设计模式
命令模式(Command)

命令模式(Command)

作者: 秀儿2020 | 来源:发表于2020-07-23 17:18 被阅读0次

    定义

    将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销操作。

    本质

    封装请求

    登场角色

    • Command(命令)

      负责定义命令的接口

    • ConcreteCommand(具体的命令)

      实现命令接口

    • Receiver(接收者)

      命令接收者,真正执行命令的对象,任何对象都可以成为命令接收者,只要它能够实现命令要求实现的相应功能。

    • Client(请求者)

      创建具体的命令对象并设置命令接收者,即组装命令对象和接收者。

    • Invoker(发动者)

      开始执行命令的角色。通常持有命令对象,可以持有很多命令对象,相当于命令对象的入口。

    示例代码

    /**
     * 接收者角色,处理具体逻辑
     * 是整个命令模式中唯一处理具体代码逻辑的地方,
     * 其他的类都是直接或间接的调用到该类的方法
     */
    public class TerisMachine {
        /**
         * 真正处理向左操作的逻辑
         */
        public void toLeft(){
            System.out.println("向左");
        }
    
        /**
         * 真正处理向右操作的逻辑
         */
        public void toRight(){
            System.out.println("向右");
        }
    
        /**
         * 真正处理快速落下操作的逻辑
         */
        public void fastToBottom(){
            System.out.println("快速落下");
        }
    
        /**
         * 真正处理改变形状操作的逻辑
         */
        public void transform(){
            System.out.println("改变形状");
        }
    }
    
    /**
     * 命令抽象者
     */
    public interface Command {
        void execute();
    }
    
    
    /**
     * 具体命令,持有一个接收者角色对象
     */
    public class LeftCommand implements Command{
        private TerisMachine terisMachine;
    
        public LeftCommand(TerisMachine terisMachine) {
            this.terisMachine = terisMachine;
        }
    
        @Override
        public void execute() {
            terisMachine.toLeft();
        }
    }
    
    
    /**
     * 具体的命令
     */
    public class RightCommand implements Command{
        private TerisMachine terisMachine;
    
        public RightCommand(TerisMachine terisMachine) {
            this.terisMachine = terisMachine;
        }
    
        @Override
        public void execute() {
            terisMachine.toRight();
        }
    }
    
    /**
     * 具体的命令
     */
    public class FallCommand implements Command{
        private TerisMachine terisMachine;
    
        public FallCommand(TerisMachine terisMachine) {
            this.terisMachine = terisMachine;
        }
    
        @Override
        public void execute() {
            terisMachine.fastToBottom();
        }
    }
    
    /**
     * 具体的命令
     */
    public class TransforCommand implements Command{
        private TerisMachine terisMachine;
    
        public TransforCommand(TerisMachine terisMachine) {
            this.terisMachine = terisMachine;
        }
    
        @Override
        public void execute() {
            terisMachine.transform();
        }
    }
    
    
    /**
     * 请求者
     */
    public class Buttons {
        private LeftCommand leftCommand;
        private RightCommand rightCommand;
        private FallCommand fallCommand;
        private TransforCommand transforCommand;
    
        public void setLeftCommand(LeftCommand leftCommand) {
            this.leftCommand = leftCommand;
        }
    
        public void setRightCommand(RightCommand rightCommand) {
            this.rightCommand = rightCommand;
        }
    
        public void setFallCommand(FallCommand fallCommand) {
            this.fallCommand = fallCommand;
        }
    
        public void setTransforCommand(TransforCommand transforCommand) {
            this.transforCommand = transforCommand;
        }
    
        public void toLeft(){
            leftCommand.execute();
        }
    
        public void toRight(){
            rightCommand.execute();
        }
    
        public void fall(){
            fallCommand.execute();
        }
    
        public void transform(){
            transforCommand.execute();
        }
    }
    
    
    public class Client {
        public static void main(String[] args){
            //构造俄罗斯方块游戏
            TerisMachine terisMachine = new TerisMachine();
            //构造四种命令
            LeftCommand leftCommand = new LeftCommand(terisMachine);
            RightCommand rightCommand = new RightCommand(terisMachine);
            FallCommand fallCommand = new FallCommand(terisMachine);
            TransforCommand transforCommand = new TransforCommand(terisMachine);
            //按钮可以执行不同的命令
            Buttons buttons = new Buttons();
            buttons.setLeftCommand(leftCommand);
            buttons.setRightCommand(rightCommand);
            buttons.setFallCommand(fallCommand);
            buttons.setTransforCommand(transforCommand);
            //具体按下哪个按钮玩家说了算
            buttons.toLeft();
            buttons.toRight();
            buttons.fall();
            buttons.transform();
        }
    }
    

    运行结果

    向左
    向右
    快速落下
    改变形状
    

    优点

    • 更松散的耦合

      命令模式使得发起命令的对象(客户端),和具体的命令的对象(接收者)对象完全解耦,也就是说发起命令的对象完全不知道具体实现对象是谁,也不知道如何实现。

    • 更动态的控制

      命令模式把请求封装起来,可以动态的对它进行参数化、队列化和日志化等操作,从而使得系统更加灵活。

    • 很自然的复合命令

      命令模式中的命令对象能够很容易的组合成复合命令,也就是前面讲的宏命令,从而使系统操作更简单,功能更强大。

    • 更好的扩展性

      由于发起命令的对象和具体的实现完全解耦,因此扩展新的命令就很容易,只需要实现新的命令对象,然后在装配的时候,把具体的实现对象设置到命令对象中,然后就可以使用这个命令对象,已有的实现完全不用变化。

    何时使用

    • 需要抽象出待执行的动作,然后以参数的形式提供出来。类似于过程设计中的回调机制,而命令模式正式回调机制的一个面向对象的替代品。
    • 在不同的时候指定、排列和执行请求。一个命令对象可以有与初始请求无关的生命期。
    • 需要支持取消操作。
    • 支持修改日志功能,这样当系统崩溃时,这些修改可以被重做一次。
    • 需要支持事务操作。

    相关文章

      网友评论

        本文标题:命令模式(Command)

        本文链接:https://www.haomeiwen.com/subject/uqbhlktx.html