Java命令设计模式优雅解耦命令和执行提高代码可维护性

作者:.番茄炒蛋 时间:2023-11-23 06:25:46 

介绍

Java命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,从而使不同的请求可以进行参数化,并支持请求的排队,记录日志,撤销操作等.

在命令模式中,将命令请求者(Invoker),命令接收者(Receiver)和命令对象(Command)进行了解耦,使得它们可以独立地变化.具体的说,命令对象封装了一个特定的请求和其对应的操作,Invoker对象负责调用命令来执行请求,而Receiver对象则负责实际执行命令所代表的操作.

在Java中,可以通过定义一个接口来定义命令对象的基本行为,然后再定义具体的命令对象实现该接口.Invoker对象可以包含一个或多个命令对象,可以通过调用命令对象的execute()方法来执行相应的命令.而Receiver对象则负责实际执行命令所代表的操作,其具体实现可以再命令对象的execute()方法中调用.

实现

命令对象接口

public interface Command {
   /**
    * 执行
    */
   void execute();
   /**
    * 撤销
    */
   void undo();
}

具体命令对象

public class ConcreteCommand1 implements Command {
   private Receiver receiver;
   private boolean isExecute;
   public ConcreteCommand1(Receiver receiver) {
       this.receiver = receiver;
   }
   /**
    * 执行
    */
   @Override
   public void execute() {
       receiver.action1();
       isExecute = true;
   }
   /**
    * 撤销
    */
   @Override
   public void undo() {
       if (isExecute) {
           receiver.undoAction1();
           isExecute = false;
       }
   }
}
public class ConcreteCommand2 implements Command {
   private Receiver receiver;
   private boolean isExecute;
   public ConcreteCommand2(Receiver receiver) {
       this.receiver = receiver;
   }
   /**
    * 执行
    */
   @Override
   public void execute() {
       receiver.action2();
       isExecute = true;
   }
   /**
    * 撤销
    */
   @Override
   public void undo() {
       if (isExecute) {
           receiver.undoAction2();
           isExecute = false;
       }
   }
}

命令接收者

public class Receiver {
   public void action1() {
       System.out.println("Receiver.action1() 被调用...");
   }
   public void action2() {
       System.out.println("Receiver.action2() 被调用...");
   }
   public void undoAction1(){
       System.out.println("Receiver.undoAction1() 被调用...");
   }
   public void undoAction2(){
       System.out.println("Receiver.undoAction2() 被调用...");
   }
}

命令请求者

public class Invoker {
   private List<Command> commandList = new ArrayList<>();
   /**
    * 添加命令
    *
    * @param command
    */
   public void addCommand(Command command) {
       commandList.add(command);
   }
   /**
    * 执行命令
    */
   public void executeCommands() {
       commandList.forEach(Command::execute);
   }
   /**
    * 撤销命令
    */
   public void undoCommands() {
       for (int i = commandList.size() - 1; i >= 0; i--) {
           commandList.get(i).undo();
       }
   }
}

测试

public class Demo {
   public static void main(String[] args) {
       Receiver receiver = new Receiver();
       Command command1 = new ConcreteCommand1(receiver);
       Command command2 = new ConcreteCommand2(receiver);
       Invoker invoker  = new Invoker();
       invoker.addCommand(command1);
       invoker.addCommand(command2);
       invoker.executeCommands();
       invoker.undoCommands();
   }
}

Java命令设计模式优雅解耦命令和执行提高代码可维护性

再示例代码中,定义了两个具体的命令对象实现,分别是ConcreteCommand1和ConcreteCommand2,它们都实现了Command接口,并且支持撤销操作.每个ConcreteCommand对象内部维护了一个boolean类型的isExecute变量,表示该命令是否已经执行过.如果execute()方法中,执行具体的命令操作,并将isExecute设为true.再undo()方法中,如果该命令已经执行过,则执行与execute()方法相反的操作,并将isExecute设为false.Receiver类是命令接收者,它实际执行命令所代表的操作.Invoker类中包含了一个Command对象列表,它通过addCommand()方法向其中添加具体的Command对象,executeCommand()用于执行所有添加的Command对象,而undoCommands()方法则用于撤销所有添加的Command对象,执行与撤销的顺序正好相反.

总结

优点

  • 解耦合,命令模式可以将命令请求者和命令接收者之间解耦合,使得它们之间不直接产生相互作用,从而提高系统的灵活性和可扩展性

  • 扩展性,由于命令模式将请求封装成对象,因此可以方便地新增或修改命令,而不影响其他对象的运行.同时,也可以方便地新增或修改命令接收者,从而实现系统功能的灵活变化.

  • 撤销操作,命令模式可以支持撤销操作,使得系统具有回滚功能,增强了系统的容错性.

缺点

  • 系统复杂性,使用命令模式需要增加额外的类和接口,从而增加了系统的复杂性

  • 性能损失.由于需要将请求封装成对象,因此可能会导致系统性能的降低,特别是再处理大量请求时

应用场景

  • 撤销操作,如果系统需要支持撤销操作,那么命令模式是一个非常好的选择.例如:文本编辑器中的"撤销"和"重做"操作.

  • 日志记录,命令模式可以用来记录请求日志,从而实现系统的日志功能.例如:使用命令模式记录用户的操作记录,实现系统的审计功能.

  • 队列请求.如果需要将请求排队,可以使用命令模式来管理请求队列.例如:使用命令模式管理操作系统的I/O请求队列.

来源:https://blog.csdn.net/qq_43135259/article/details/129499805

标签:Java,命令,设计模式
0
投稿

猜你喜欢

  • Java 如何安全的发布对象

    2022-08-09 05:38:52
  • springboot拦截器过滤token,并返回结果及异常处理操作

    2023-02-19 11:45:50
  • 解决RestTemplate加@Autowired注入不了的问题

    2022-07-14 03:00:48
  • Android仿支付宝支付从底部弹窗效果

    2022-04-30 10:37:13
  • java开发之Jdbc分页源码详解

    2021-10-28 16:06:48
  • MultipartFile中transferTo(File file)的路径问题及解决

    2023-11-12 00:07:08
  • Spring Boot JPA中使用@Entity和@Table的实现

    2023-11-22 11:49:58
  • Spring5中的WebClient使用方法详解

    2023-08-05 14:50:24
  • SpringBoot应用线上重启脚本的命令详解

    2022-02-05 18:21:52
  • 快速解决设置Android 23.0以上版本对SD卡的读写权限无效的问题

    2021-08-26 09:31:43
  • C#实现猜数字小游戏

    2023-01-13 16:39:38
  • 如何获取Android设备挂载的所有存储器

    2023-08-16 12:44:41
  • Android中Snackbar的使用方法及小技巧

    2023-10-30 03:13:31
  • c# 快速排序算法

    2021-10-18 07:33:20
  • java的引用类型的详细介绍

    2022-05-15 09:34:40
  • java中Vector类的常用方法详解

    2023-11-26 10:29:07
  • 使用Prometheus+Grafana的方法监控Springboot应用教程详解

    2023-10-31 13:08:12
  • Android开发中通过手机号+短信验证码登录的实例代码

    2023-03-10 10:57:13
  • 浅析Android手机卫士保存手机安全号码

    2021-08-17 20:02:52
  • springboot html调用js无效400问题及解决

    2023-06-24 02:11:54
  • asp之家 软件编程 m.aspxhome.com