zoukankan      html  css  js  c++  java
  • [设计模式]命令模式概述

    主要是从 Head Fisrt 设计模式中学习到知识;

    1. 定义命令模式

      命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

      讲明白点就是,命令模式有点类似 http的”请求-响应“模型,外部调用者不需要知道命令内部如何,客户端只需要发起请求,就能得到响应,有人想要说,这不是面向对象的封装的概念吗,但是命令模式更像是一种行为类模式,实现低耦合的目标,处理将命令封装成接口,还引入了请求者、接受者的概念,这些会在下面了解到。

      优点:

      • 调用者和接收者彼此之间松耦合,调用者不会持有接收者的引用,只是知道命令中封装了接收者的信息,需要完成这个命令的时候直接调用命令的execute()即可;
      • 符合设计模式的“开-闭原则”,1. 当加入新的命令和命令接收者的时候,调用者可以不修改代码直接访问该命令; 2. 当加入新的调用者的时候,不需要修改命令和命令接收者的代码,调用者可以使用现有的命令;
      • 可以将方便的将多条命令简单封装到一个新的命令,例如 剪切 就可以将 复制、删除两个命令封装起来合并成一个新的命令;
      • 因为命令本身知道接收者的信息,可以将命令进行持久化操作,以便在需要的时候拿出来再次执行,和这个差不多的还有就是命令队列,可以将命令形成一个队列,当系统有资源或者允许的情况下进行命令的取出,调用,控制进行的命令数;
      • 记录命令执行日志,利用调用者记录某个检查点之后的命令操作记录,在丢失前面操作的时候可以通过日志重新恢复,还可以实现撤回、重做的操作;

    2. 主要思想

      2.1 操作都封装在一个具体的命令类中,命令持有接收者的引用;

      2.2 调用者直接请求命令的 入口 就可以方便的调用不同的命令;

    3. 命令模式的实现

      3.1 下图是命令模式中用到的主要类的类图:

      

      其中Client是客户端请求,Invoker是请求者, Command是命令接口, ConcreteCommand是具体的命令类,其中持有 Receiver(接受者)的引用,Client请求Invoker调用命令,Invoker获得需要的命令之后,执行execute()方法,ConcreteCommand 调用设置好的接受者的一系列方法,完成命令请求,在这一些列请求中,只有ConcreteCommand知道具体的命令执行者是谁,其他角色都是不知道的,只知道调用该命令就能完成自己想要的操作,后面加入新的命令,只要告诉调用者,调用者能不修改代码就能直接调用新的命令,如果加入新的调用者,那么前面调用者能使用的命令,新的调用者都是可以使用的。

      3.2 下面是命令模式的具体代码实现

       这是命令类接口,用来交互的接口:

    public interface Command {
      public void execute();
    }

      这是具体的命令,具体的命令决定命令真正的执行者和执行的内容:  

    public class ConcreteCommand implements Command{
      private Receiver receiver;
    
      public void execute() {
         recevier.action1();
         receiver.action2();
      }
    }

      这是命令的调用者,调用者可以持有一系列命令,并提供出来接口供用户使用:

    public class Invoker {
      List<Command> commands;
    
      public Invoker(List<Command> commands){
        this.commands = commands;
      }       
    
      public void addCommand(Command command){
        this.commands.add(command);
      }
    
    // 这里采用下标的方式,实际中会提供多个接口或者更加可读的调用方式
      public void doIt(int slot){
         commands.get(slot).execute();
      }
    
    }

      这是接收者代码,接收者提供他能提供的一系列动作集合,供给命令调用:

    public class Receiver {
      public void action1(){}
    
      public void action2(){}
    
      public void action3(){}
    }

      命令模式还能通过记录操作日志的方式来实现重做和撤销的操作,还可以通过组合多个命令的形式,实现宏操作;

    总结:

      命令模式将请求者和接收者完全解耦, 通过传递命令接口来实现对功能的请求,可以对代码很少修改或者不修改就可以添加新的命令和调用者,还可以实现命令队列、持久化,重做,撤销,组合等功能;缺点就是每一个操作都需要一个命令类的封装,会造成系统中有很多类的存在。

    写得比较好的文章:

    [解析Java设计模式编程中命令模式的使用] https://www.jb51.net/article/79500.htm

    [命令模式 | 菜鸟教程] http://www.runoob.com/design-pattern/command-pattern.html

  • 相关阅读:
    PHP数组(数组正则表达式、数组、预定义数组)
    面向对象。OOP三大特征:封装,继承,多态。 这个讲的是【封存】
    uvalive 3938 "Ray, Pass me the dishes!" 线段树 区间合并
    LA4329 Ping pong 树状数组
    HDU 1257 最少拦截系统
    HDU 1260 Tickets
    codeforce 621D
    codeforce 621C Wet Shark and Flowers
    codeforce 621B Wet Shark and Bishops
    codeforce 621A Wet Shark and Odd and Even
  • 原文地址:https://www.cnblogs.com/zhuangmingnan/p/9398977.html
Copyright © 2011-2022 走看看