深入浅出设计模式 - 命令模式

简介: 深入浅出设计模式 - 命令模式

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌

Java知识图谱点击链接:体系化学习Java(Java面试专题)

💕💕 感兴趣的同学可以收藏关注下不然下次找不到哟💕💕

1687926118521.jpg

1、什么是命令模式

命令模式是一种行为设计模式,它将请求封装成一个对象,从而允许我们根据不同的请求将客户端参数化,将请求排入队列或记录请求日志,并支持可撤销的操作。

2、命令模式的优缺点

命令模式的优点包括:

  1. 解耦合:命令模式可以将发送者和接收者解耦,发送者不需要知道接收者的具体实现细节,只需通过命令对象来发送请求。

  2. 可扩展性:通过添加新的具体命令类,可以很容易地扩展命令模式,而无需修改已有的代码,符合开闭原则。

  3. 可以实现撤销和重做:命令模式可以记录命令的执行历史,从而支持撤销和重做操作。

  4. 支持事务性操作:命令模式可以将多个命令组合成一个复合命令,从而实现事务性操作,确保多个命令的执行和撤销都成功。

  5. 可以实现日志和审计功能:由于命令模式记录了命令的执行历史,可以用于实现日志和审计功能。

命令模式的缺点包括:

  1. 代码复杂性增加:引入命令对象和调用者对象,会增加代码的复杂性和额外的类。

  2. 可能会导致类爆炸:如果系统中有大量的命令类,可能会导致类的数量爆炸,增加系统的复杂性。

  3. 执行效率降低:由于命令模式需要将请求封装成对象,可能会导致执行效率降低。

综上所述,命令模式在需要将请求发送者和接收者解耦、支持撤销和重做、实现事务性操作等场景下非常有用。但在一些简单的场景下,引入命令模式可能会增加代码复杂性,因此需要根据具体情况进行权衡和选择。

3、命令模式的应用场景

命令模式适用于以下场景:

  1. 需要解耦发送者和接收者:当需要将请求发送者和接收者解耦,使得发送者不需要知道接收者的具体实现细节时,可以使用命令模式。

  2. 支持撤销和重做操作:命令模式可以记录命令的执行历史,从而支持撤销和重做操作。例如,在文本编辑器中,可以使用命令模式实现对文本的撤销和重做操作。

  3. 实现事务性操作:命令模式可以将多个命令组合成一个复合命令,从而实现事务性操作。例如,在数据库操作中,可以使用命令模式将多个数据库操作封装成一个事务命令,保证多个操作的执行和撤销都成功。

  4. 实现日志和审计功能:由于命令模式记录了命令的执行历史,可以用于实现日志和审计功能。例如,在系统中记录用户操作日志或审计操作。

  5. 需要支持命令的延迟执行或异步执行:命令模式可以将命令对象存储起来,延迟执行或异步执行。例如,在任务调度系统中,可以使用命令模式将任务封装成命令对象,然后由调度器定时执行。

总之,命令模式适用于需要将请求发送者和接收者解耦、支持撤销和重做、实现事务性操作、实现日志和审计功能,以及支持命令的延迟执行或异步执行的场景。

4、命令模式的结构

命令模式的结构包括以下几个主要角色:

  1. 命令接口(Command Interface):定义了执行命令的方法,通常包括一个execute()方法。所有具体命令类都要实现该接口。

  2. 具体命令(Concrete Command):实现了命令接口,负责执行具体的操作。它包含了接收者对象,并调用接收者的方法来完成命令的执行。

  3. 接收者(Receiver):执行具体操作的对象。命令模式将命令和接收者解耦,使得命令对象不需要了解接收者的具体实现。

  4. 调用者(Invoker):负责调用命令对象来执行请求。它持有一个命令对象,并在需要执行命令时调用命令的execute()方法。

  5. 客户端(Client):创建具体命令对象并设置其接收者,然后将命令对象传递给调用者来执行。

    5、命令模式的工作原理

命令模式的工作原理如下:

  1. 客户端创建具体命令对象,并设置其接收者。具体命令对象实现了命令接口,其中包含了执行具体操作的逻辑,并持有一个接收者对象的引用。

  2. 客户端将命令对象传递给调用者。调用者是命令的执行者,它持有命令对象,并在需要执行命令的时候调用命令的execute()方法。

  3. 调用者调用命令对象的execute()方法。这个方法会调用接收者对象的相应方法来执行具体操作。

  4. 接收者执行具体操作。接收者是命令的实际执行者,它负责执行具体的操作逻辑。

通过命令模式,发送者和接收者之间解耦,发送者只需要知道如何调用命令对象,而不需要知道具体的接收者和操作。这样可以更灵活地组织和管理命令,并支持撤销、重做、事务、日志等功能。

命令模式的核心思想是将请求封装成对象,从而使得请求的发送者和接收者解耦,并且可以方便地扩展和修改命令。它适用于需要将请求封装成独立对象,并且支持撤销、重做、事务等操作的场景。

6、命令模式的代码案例

以下是一个简单的命令模式的代码案例:

package com.pany.camp.design.principle.command;

/**
 *
 * @description:  接口
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-28 12:26
 */
public interface Command {
   
   
    void execute();
}

定义接收者类

package com.pany.camp.design.principle.command;

/**
 *
 * @description:  定义接收者类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-28 12:26
 */
public class Receiver {
   
   
    public void action() {
   
   
        System.out.println("执行具体操作");
    }
}

定义具体命令类,实现命令接口

package com.pany.camp.design.principle.command;

/**
 *
 * @description: 定义具体命令类,实现命令接口
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-28 12:26
 */
public class ConcreteCommand implements Command {
   
   
    private Receiver receiver;

    public ConcreteCommand(Receiver receiver) {
   
   
        this.receiver = receiver;
    }

    public void execute() {
   
   
        receiver.action();
    }
}

定义调用者类

package com.pany.camp.design.principle.command;

/**
 *
 * @description:  调用者类
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-28 12:29
 */
public class Invoker {
   
   
    private Command command;

    public void setCommand(Command command) {
   
   
        this.command = command;
    }

    public void executeCommand() {
   
   
        command.execute();
    }
}

客户端代码如下:

package com.pany.camp.design.principle.command;

/**
 *
 * @description:  客户端
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-28 12:27
 */
public class Client {
   
   

    public static void main(String[] args) {
   
   
        // 创建接收者对象
        Receiver receiver = new Receiver();

        // 创建具体命令对象,并设置接收者
        Command command = new ConcreteCommand(receiver);

        // 创建调用者对象,并设置具体命令
        Invoker invoker = new Invoker();
        invoker.setCommand(command);

        // 调用者执行命令
        invoker.executeCommand();
    }
}

Command接口定义了命令的执行方法execute()。具体命令类ConcreteCommand实现了Command接口,并持有一个接收者对象的引用,在execute()方法中调用接收者的action()方法来执行具体操作。接收者类Receiver定义了具体操作的逻辑。调用者类Invoker持有一个命令对象,并提供了设置命令和执行命令的方法。在客户端代码中,创建接收者对象、具体命令对象和调用者对象,并通过调用者对象来执行命令。

输出如下:

执行具体操作

Process finished with exit code 0

1686494501743.jpg

💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊

1687869804912.jpg

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
3天前
|
设计模式 UED
二十三种设计模式:解锁软件开发的神器:命令模式与撤销重做功能
二十三种设计模式:解锁软件开发的神器:命令模式与撤销重做功能
|
3天前
|
设计模式 小程序 Java
Java设计模式【十五】:命令模式
Java设计模式【十五】:命令模式
26 0
|
7月前
|
设计模式 敏捷开发 C++
行为型设计模式07-命令模式
行为型设计模式07-命令模式
21 0
|
7月前
|
设计模式 语音技术
设计模式12 - 命令模式【Command Pattern】
设计模式12 - 命令模式【Command Pattern】
28 0
|
3天前
|
设计模式 存储 Java
【搞懂设计模式】命令模式:从遥控器到编程的妙用!
【搞懂设计模式】命令模式:从遥控器到编程的妙用!
7 0
|
3天前
|
设计模式 Java 调度
【设计模式系列笔记】命令模式
命令模式是一种行为设计模式,它将请求封装成一个对象,从而允许使用不同的请求、队列或日志请求参数化客户端对象,同时支持撤销操作。
30 1
|
3天前
|
设计模式 Java 调度
小谈设计模式(24)—命令模式
小谈设计模式(24)—命令模式
|
3天前
|
设计模式 存储 Java
认真学习设计模式之命令模式(Command Pattern)
认真学习设计模式之命令模式(Command Pattern)
84 0
|
3天前
|
设计模式 Java
23种设计模式,命令模式的概念优缺点以及JAVA代码举例
【4月更文挑战第7天】命令模式是一种行为设计模式,它将请求或简单操作封装为一个对象。这种模式允许用户通过调用对象来参数化其他对象的方法,并能保存、排队和执行方法调用。
26 1
|
3天前
|
设计模式 存储 Java
【设计模式】命令模式
【设计模式】命令模式