博客
关于我
一文理解设计模式--命令模式(Command)
阅读量:534 次
发布时间:2019-03-09

本文共 4715 字,大约阅读时间需要 15 分钟。

命令模式(Command Pattern)

定义

命令模式通过将操作包装成对象来实现操作的撤销、恢复上一个状态、重复执行命令等功能。例如,在编程中,这种模式常用于支持撤销(undo)和重做(redo)的功能,比如代码编辑器中的命令历史记录。

适用场景

  • 需要撤销、重做功能:比如代码编辑器支持撤销上一次操作或重做。
  • 命令排序:根据不同的情况对多个命令进行排序并组合执行。
  • 系统崩溃恢复:在系统崩溃时,命令可以持久化存储,恢复时重新执行记录的命令。
  • 角色说明

    • Command(命令抽象类):所有命令的基类,每个命令都必须实现execute方法。
    • ConcreteCommand(具体命令实现类):具体实现Command中的execute方法。
    • Invoker(控制器):负责执行命令的调用者,维护撤销栈和重做栈。
    • Receiver(接收者):命令操作的执行目标,维护相关状态。

    代码示例

    public abstract class Command {    public abstract void execute(Receiver receiver);    public abstract void undo();    public abstract void redo();    @Override    public abstract String toString();}

    隐形咒命令

    public class InvisibilityCommand extends Command {    private Receiver receiver;    @Override    public void execute(Receiver receiver) {        receiver.setVisibility(Visibility.INVISIBLE);        this.receiver = receiver;    }    @Override    public void undo() {        if (receiver != null) {            receiver.setVisibility(Visibility.VISIBLE);        }    }    @Override    public void redo() {        if (receiver != null) {            receiver.setVisibility(Visibility.INVISIBLE);        }    }    @Override    public String toString() {        return "invisible";    }}

    缩小命令

    public class ShrinkCommand extends Command {    private Size oldSize;    private Receiver receiver;    @Override    public void execute(Receiver receiver) {        oldSize = receiver.getSize();        receiver.getSize(Size.SMALL);        this.receiver = receiver;    }    @Override    public void undo() {        if (oldSize != null && receiver != null) {            Size temp = receiver.getSize();            receiver.setSize(oldSize);        }    }    @Override    public void redo() {        undo();    }    @Override    public String toString() {        return "small";    }}

    接收者抽象类

    public abstract class Receiver {    private Size size;    private Visibility visibility;    public Size getSize() {        return size;    }    public void setSize(Size size) {        this.size = size;    }    public Visibility getVisibility() {        return visibility;    }    public void setVisibility(Visibility visibility) {        this.visibility = visibility;    }    public abstract String toString();    public void printStatus() {        System.out.println(String.format("[size=%s] [visibility=%s]", getSize(), getVisibility()));    }}

    妖怪接收者

    public class GoblinReceiver extends Receiver {    public GoblinReceiver() {        setSize(Size.NORMAL);        setVisibility(Visibility.VISIBLE);    }    public String toString() {        return "GoblinReceiver";    }}

    命令调用器

    public class Invoker {    private Deque undoStack = new LinkedList<>();    private Deque redoStack = new LinkedList<>();    public void call(Command command, Receiver receiver) {        command.execute(receiver);        undoStack.offerLast(command);    }    public void undo() {        Command previousSpell = undoStack.pollLast();        if (previousSpell != null) {            redoStack.offerLast(previousSpell);            System.out.println(" undoes " + previousSpell + " command");            previousSpell.undo();        }    }    public void redo() {        Command previousSpell = redoStack.pollLast();        if (previousSpell != null) {            undoStack.offerLast(previousSpell);            System.out.println(" redoes " + previousSpell + " command");            previousSpell.redo();        }    }    @Override    public String toString() {        return "Invoker";    }}

    测试类代码

    public class App {    public static void main(String[] args) {        Invoker invoker = new Invoker();        GoblinReceiver goblinReceiver = new GoblinReceiver();        goblinReceiver.printStatus();        invoker.call(new ShrinkCommand(), goblinReceiver);        goblinReceiver.printStatus();        invoker.call(new InvisibilityCommand(), goblinReceiver);        goblinReceiver.printStatus();        invoker.undo();        goblinReceiver.printStatus();        invoker.undo();        goblinReceiver.printStatus();        invoker.redo();        goblinReceiver.printStatus();        invoker.redo();        goblinReceiver.printStatus();    }}

    屏幕输出结果

    接收者状态:[size=normal] [visibility=visible]Invoker在GoblinReceiver上执行命令 small接收者状态:[size=small] [visibility=visible]Invoker在GoblinReceiver上执行命令 invisible接收者状态:[size=small] [visibility=invisible]Invoker undoes invisible command接收者状态:[size=small] [visibility=visible]Invoker undoes small command接收者状态:[size=normal] [visibility=visible]Invoker redoes small command接收者状态:[size=small] [visibility=visible]Invoker redoes invisible command接收者状态:[size=small] [visibility=invisible]

    优缺点分析

    优点

  • 降低系统耦合度:通过Invoker解耦Command和Receiver。
  • 扩展性高:新命令可以轻松加入系统。
  • 支持命令队列和宏命令:可以在各种情况下排队和执行命令。
  • 易于实现undo和redo:提供了标准的操作流程。
  • 缺点

  • 大量具体命令类:需要为每个命令定义独立的类,增加了开发复杂度。
  • 转载地址:http://wpisz.baihongyu.com/

    你可能感兴趣的文章
    i5 10400f和r5 3600怎么选i5 10400f和r5 3600性能测评
    查看>>
    Ubuntu:系统重刷中那些奇奇怪怪的问题
    查看>>
    SPICE:基本介绍和简单语法
    查看>>
    模拟集成:MOS管的工作区小误区(简单版)
    查看>>
    Android AIDL了解多少
    查看>>
    [20210506]LeetCode每日一题 - 1720. 解码异或后的数组
    查看>>
    2.基于yolov的行人进出双向计数
    查看>>
    TensorFlow 框架学习资源
    查看>>
    python的GUI编程(wxpython)
    查看>>
    flink启动(二)
    查看>>
    27.HTML+CSS3 实现长阴影网页特效
    查看>>
    29.HTML+CSS3 实现酷炫 Loading 特效
    查看>>
    前端开发进阶手册.pdf
    查看>>
    41.clip-path 滚动特效
    查看>>
    【第 242 期】小智在这3年开发中遇到的 CSS 问题及解决方案,有大佬帮他总结好了 !...
    查看>>
    73.使用HTML CSS和jQuery进行水平页面滚动
    查看>>
    110.无限叠卡特效
    查看>>
    面试官:为什么 Promise 比setTimeout() 快?
    查看>>
    【Java基础】网络编程-RMI远程调用
    查看>>
    软件架构设计和MESH经验之谈
    查看>>