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();
}
}
再示例代码中,定义了两个具体的命令对象实现,分别是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


猜你喜欢
- Bean Searcher 号称 任何复杂的查询都可以 一行代码搞定,但 Mybatis Plus 似乎也有类似的动态查询功能,它们有怎样的
- 在项目中,分页是一个项目中必不可少的,它可以防止我们从数据库中进行大量数据查询时速度变慢,提高我们的查询效率。1、定义分页模型:PageMo
- 本文实例讲述了Java Web项目部署在Tomcat运行出错与解决方法。分享给大家供大家参考,具体如下:1、在部署Java Web项目的过程
- 本文实例为大家分享了C# FTP操作类的具体代码,可进行FTP的上传,下载等其他功能,支持断点续传,供大家参考,具体内容如下FTPHelpe
- 本文实例讲述了Android编程实现横竖屏切换时不销毁当前activity和锁定屏幕的方法。分享给大家供大家参考,具体如下:首先在Maini
- 本章目标整合 Mybatis ,并集成 Druid 数据源可视化监控 Druid 数据源使用 JPA 生成数据表利用注解实现数据库的事物利用
- YAMLSpring Boot 提供了大量的自动配置,极大地简化了spring 应用的开发过程,当用户创建了一个 Spring Boot 项
- ThreadLocal与线程成员变量还有区别,ThreadLocal该类提供了线程局部变量。这个局部变量与一般的成员变量不一样,Thread
- 最近在改写WebApp时要将以前用泛型处理例程写的Captcha 改成使用WebApi 来实作机制,在实作的过程中发现使用IRequires
- 一. Thread.yield( )方法:使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。cpu会从众多的可执行态里选择,也就是说
- using System;using System.Collections.Generic;using System.Text;using
- Android 回调前言:Android中的回调最经典的就是点击事件设置监听(一般通过switch(v.getId()))这里写
- 理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣。Proxy是比较有用途的一种模式
- java异常分为两大类,Checked异常和Runtime异常,Checked异常都是在编译阶段可以被处理的异常。Checked异常和Run
- 在Android应用中,图片裁剪也是一个经常用到的功能。Android系统中可以用隐式意图调用系统应用进行裁剪,但是这样做在不同的手机可能表
- WPF在样式定义和UI动画上面相对于以前的技术有了不少的提升,下面给出WPF技术实现钟表的效果:1、Visual Studio新建一个WPF
- 可以使用 graphics2D 类提供的 shear(
- 本文实例讲述了C#调用存储过程的方法。分享给大家供大家参考,具体如下:CREATE PROCEDURE [dbo].[GetNameById
- 本文实例讲述了WinForm实现的图片拖拽与缩放功能。分享给大家供大家参考,具体如下:最近做项目的时候遇到上传施工平面布置图,查看,因为图片
- springboot+spring data jpa实现新增及批量新增spring data jpa (以下简称jpa)。这个orm其实和m