设计模式之命令模式:原理、实现与应用

news2025/3/25 5:44:49
引言

命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为对象,从而使你可以用不同的请求对客户进行参数化。命令模式支持请求的排队、记录日志、撤销操作等功能。本文将深入探讨命令模式的原理、实现方式以及实际应用场景,帮助你更好地理解和使用这一设计模式。


1. 命令模式的核心概念

1.1 什么是命令模式?

命令模式是一种行为型设计模式,它将请求封装为对象,从而使你可以用不同的请求对客户进行参数化。命令模式支持请求的排队、记录日志、撤销操作等功能。

1.2 命令模式的应用场景
  • 请求排队:如任务队列、线程池等。

  • 撤销操作:如文本编辑器中的撤销功能。

  • 日志记录:如记录用户操作的日志。

  • 事务处理:如数据库事务的提交和回滚。


2. 命令模式的实现方式

2.1 基本结构

命令模式通常包含以下几个角色:

  • 命令接口(Command):定义执行操作的接口。

  • 具体命令(Concrete Command):实现命令接口,封装具体的操作。

  • 接收者(Receiver):执行命令的对象。

  • 调用者(Invoker):持有命令对象,并调用命令的执行方法。

  • 客户端(Client):创建命令对象并设置其接收者。

2.2 代码示例
// 命令接口
public interface Command {
    void execute();
}

// 具体命令
public class ConcreteCommand implements Command {
    private Receiver receiver;

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

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

// 接收者
public class Receiver {
    public void action() {
        System.out.println("Receiver action");
    }
}

// 调用者
public class Invoker {
    private Command command;

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

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

// 客户端代码
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();
    }
}

3. 命令模式的最佳实践

3.1 支持撤销操作
  • 撤销操作:通过命令模式实现撤销操作,记录命令的执行状态。

  • 重做操作:通过命令模式实现重做操作,记录命令的执行历史。

3.2 支持日志记录
  • 日志记录:通过命令模式记录用户操作的日志,便于追踪和审计。

  • 事务处理:通过命令模式实现事务的提交和回滚。

3.3 遵循单一职责原则
  • 单一职责:每个命令只负责一个操作,保持职责单一。

  • 高内聚低耦合:命令模式使得系统更加高内聚低耦合。


4. 命令模式的实际应用

4.1 文本编辑器

在文本编辑器中,命令模式用于实现撤销和重做功能。

// 命令接口
public interface TextCommand {
    void execute();
    void undo();
}

// 具体命令
public class InsertTextCommand implements TextCommand {
    private StringBuilder text;
    private String insertedText;
    private int position;

    public InsertTextCommand(StringBuilder text, String insertedText, int position) {
        this.text = text;
        this.insertedText = insertedText;
        this.position = position;
    }

    @Override
    public void execute() {
        text.insert(position, insertedText);
    }

    @Override
    public void undo() {
        text.delete(position, position + insertedText.length());
    }
}

// 调用者
public class TextEditor {
    private List<TextCommand> commandHistory = new ArrayList<>();
    private int currentCommandIndex = -1;

    public void executeCommand(TextCommand command) {
        command.execute();
        commandHistory.add(command);
        currentCommandIndex++;
    }

    public void undo() {
        if (currentCommandIndex >= 0) {
            TextCommand command = commandHistory.get(currentCommandIndex);
            command.undo();
            currentCommandIndex--;
        }
    }

    public void redo() {
        if (currentCommandIndex < commandHistory.size() - 1) {
            currentCommandIndex++;
            TextCommand command = commandHistory.get(currentCommandIndex);
            command.execute();
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        StringBuilder text = new StringBuilder("Hello, World!");
        TextEditor editor = new TextEditor();

        TextCommand insertCommand = new InsertTextCommand(text, "Java ", 7);
        editor.executeCommand(insertCommand);
        System.out.println(text);

        editor.undo();
        System.out.println(text);

        editor.redo();
        System.out.println(text);
    }
}
4.2 任务队列

在任务队列中,命令模式用于实现任务的排队和执行。

// 命令接口
public interface Task {
    void execute();
}

// 具体命令
public class PrintTask implements Task {
    private String message;

    public PrintTask(String message) {
        this.message = message;
    }

    @Override
    public void execute() {
        System.out.println(message);
    }
}

// 调用者
public class TaskQueue {
    private Queue<Task> tasks = new LinkedList<>();

    public void addTask(Task task) {
        tasks.add(task);
    }

    public void processTasks() {
        while (!tasks.isEmpty()) {
            Task task = tasks.poll();
            task.execute();
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        TaskQueue queue = new TaskQueue();
        queue.addTask(new PrintTask("Task 1"));
        queue.addTask(new PrintTask("Task 2"));
        queue.addTask(new PrintTask("Task 3"));

        queue.processTasks();
    }
}
4.3 遥控器

在遥控器中,命令模式用于实现按钮与设备的解耦。

// 命令接口
public interface Command {
    void execute();
}

// 具体命令
public class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }
}

public class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.off();
    }
}

// 接收者
public class Light {
    public void on() {
        System.out.println("Light is on");
    }

    public void off() {
        System.out.println("Light is off");
    }
}

// 调用者
public class RemoteControl {
    private Command command;

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

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

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Light light = new Light();
        Command lightOn = new LightOnCommand(light);
        Command lightOff = new LightOffCommand(light);

        RemoteControl remote = new RemoteControl();
        remote.setCommand(lightOn);
        remote.pressButton();

        remote.setCommand(lightOff);
        remote.pressButton();
    }
}

5. 命令模式的优缺点

5.1 优点
  • 解耦:命令模式将请求的发送者与接收者解耦,使得请求的发送者无需知道具体的接收者。

  • 扩展性:通过添加新的命令类,可以轻松扩展系统的功能。

  • 支持撤销和重做:命令模式支持撤销和重做操作,提高了系统的灵活性。

5.2 缺点
  • 类膨胀:如果系统中命令类过多,可能会导致类膨胀。

  • 复杂性:命令模式增加了系统的复杂性,特别是在需要支持撤销和重做的情况下。


结语

命令模式是设计模式中用于封装请求的经典模式之一,适用于需要将请求的发送者与接收者解耦的场景。通过掌握命令模式的原理、实现方式以及最佳实践,你可以在实际开发中更好地应用这一模式。希望本文能为你的设计模式学习之旅提供一些实用的指导!


如果你有具体的需求或想要深入探讨某个主题,请告诉我,我可以进一步调整内容!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2320280.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

南京审计大学:《 面向工程审计行业的DeepSeek大模型应用指南》.pdf(免费下载)

大家好&#xff0c;我是吾鳴。 今天吾鳴要给大家分享的是由南京审计大学出品的《面向工程审计行业的DeepSeek大模型应用指南》&#xff0c;这份报告与《面向审计行业DeepSeek大模型操作指南》不同&#xff0c;这份报告更多的讲述DeepSeek怎么与工程审计行业结合&#xff0c;应该…

【前端】Canvas画布实现在线的唇膏换色功能

【前端】Canvas画布实现在线的唇膏换色功能 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 【前端】Canvas画布实现在线的唇膏换色功能背景概述以下是我们的实现方法!第一步 — 找…

arcgispro加载在线地图

World_Imagery (MapServer)https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer添加arcgis server WMTS 服务 by xdcxdc.at xdc的个人站点。博客请转至 http://i.xdc.at/ http://xdc.at/map/wmts 添加WMTS服务器

华为网路设备学习-16 虚拟路由器冗余协议(VRRP)

VRRP是针对干线上三层网络设备&#xff08;如&#xff1a;路由器、防火墙等&#xff09;的网络虚拟化技术&#xff0c;提供冗余和状态监测等功能。确保在网络中的单点故障发生时&#xff0c;能够快速切换到备份设备&#xff0c;从而保证网络通信的连续性和可靠性。‌ VRRP通过…

封装一个分割线组件

最终样式 Vue2代码 <template><div class"sep-line"><div class"sep-label"><span class"sep-box-text"><slot>{{ title }}</slot> <!-- 默认插槽内容&#xff0c;如果没有传递内容则使用title -->&…

网络HTTPS协议

Https HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;是 HTTP 协议的加密版本&#xff0c;它使用 SSL/TLS 协议来加密客户端和服务器之间的通信。具体来说&#xff1a; • 加密通信&#xff1a;在用户请求访问一个 HTTPS 网站时&#xff0c;客户端&#x…

OSASIS(One-Shot Structure-Aware Stylized Image Synthesis)

文章目录 摘要abstract论文摘要方法损失函数实验结论 总结 摘要 本周阅读了一篇关于新型图像风格化的论文《One-Shot Structure-Aware Stylized Image Synthesis》&#xff0c;旨在解决现有GAN模型在风格化过程中难以保持输入图像结构的问题。通过分离图像的结构和语义信息&am…

C++学习之网盘项目单例模式

目录 1.知识点概述 2.单例介绍 3.单例饿汉模式 4.饿汉模式四个版本 5.单例类的使用 6.关于token的作用和存储 7.样式表使用方法 8.qss文件中选择器介绍 9.qss文件样式讲解和测试 10.qss美化登录界面补充 11.QHTTPMULTIPART类的使用 12.文件上传协议 13.文件上传协议…

Apache Flink技术原理深入解析:任务执行流程全景图

前言 本文隶属于专栏《大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见大数据技术体系 思维导图 📌 引言 Apache Flink 作为一款高性能的分布式流处理引擎,其内部执行机制精妙而复杂。本文将…

RAG(Retrieval-Augmented Generation)基建之PDF解析的“魔法”与“陷阱”

嘿&#xff0c;亲爱的算法工程师们&#xff01;今天咱们聊一聊PDF解析的那些事儿&#xff0c;简直就像是在玩一场“信息捉迷藏”游戏&#xff01;PDF文档就像是个调皮的小精灵&#xff0c;表面上看起来规规矩矩&#xff0c;但当你想要从它那里提取信息时&#xff0c;它就开始跟…

C语言【文件操作】详解中(会使用fgetc,fputc,fgets,fputs,fscanf,fprintf,fread,fwrite函数)

引言 介绍和文件操作中文件的顺序读写相关的函数 看这篇博文前&#xff0c;希望您先仔细看一下这篇博文&#xff0c;理解一下文件指针和流的概念&#xff1a;C语言【文件操作】详解上-CSDN博客文章浏览阅读606次&#xff0c;点赞26次&#xff0c;收藏4次。先整体认识一下文件是…

GpuGeek:破解算力难题,赋能AI创新与普及

文章目录 一、引言二、填补算力资源供需缺口&#xff0c;降低使用门槛三、提升算力资源利用率&#xff0c;推动高效协作四、满足多样化需求&#xff0c;支持AI技术落地五、推动算力市场创新&#xff0c;促进生态良性发展六、助力AI人才培养&#xff0c;推动行业长远发展七、结语…

扣子平台知识库不能上传成功

扣子平台知识库不能上传成功 目录 扣子平台知识库不能上传成功查看模板复制头部到自己的excel中json数据转为excel或者csv&#xff08;一定使用excel&#xff0c;csv总是报错&#xff09; 查看模板复制头部到自己的excel中 json数据转为excel或者csv&#xff08;一定使用excel&…

JVM的组成--运行时数据区

JVM的组成 1、类加载器&#xff08;ClassLoader&#xff09; 类加载器负责将字节码文件从文件系统中加载到JVM中&#xff0c;分为&#xff1a;加载、链接&#xff08;验证、准备、解析&#xff09;、和初始化三个阶段 2、运行时数据区 运行时数据区包括&#xff1a;程序计数…

c++进阶之------红黑树

一、概念 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡二叉查找树&#xff0c;它在计算机科学的许多领域中都有广泛应用&#xff0c;比如Java中的TreeMap和C中的set/map等数据结构的底层实现。红黑树通过在每个节点上增加一个颜色属性&#xff08;红色或黑色&am…

ubuntu22.04安装搜狗输入法保姆教程~

一、添加中文语言支持 1.首先打开设置,找到Language and Region 2.点击Manage Installed Languages 3.点击 Install/Remove Languages... 4.选中Chinese (simplified),点击Apply

《数据库原理》SQLServer期末复习_题型+考点

目录 题型&#xff1a; 一. 概况分析题&#xff08;5小题&#xff0c;每小题2分&#xff0c;共10分&#xff09; 二. 计算题&#xff08;3小题&#xff0c;每小题5分&#xff0c;共15分&#xff09; 三. 数据库设计&#xff08;2小题&#xff0c;每小题10分&#xff0c;共2…

Zstd(Zstandard)压缩算法

要压缩的数据量越小&#xff0c;压缩的难度就越大。这个问题对所有压缩算法都是通用的&#xff0c;原因是压缩算法从过去的数据中学习如何压缩未来的数据。但是&#xff0c;在新数据集开始时&#xff0c;没有“过去”可以构建。 官网 为了解决这种情况&#xff0c;Zstd 提供了一…

本地部署 browser-use

本地部署 browser-use 0. 引言1. 核心功能与优势2. 快速上手3. 部署 Gradio UI4. 更多示例0. 引言 Browser-Use 是一个强大的工具,旨在让 AI Agent 能够控制浏览器,从而实现各种自动化任务。它简化了 AI 与浏览器的交互,让开发者能够轻松构建能够执行网页操作的智能应用。本…

Vite管理的Vue3项目中monaco editer的使用以及组件封装

文章目录 背景环境说明安装流程以及组件封装引入依赖封装组件 外部使用实现效果 v-model实现原理 背景 做oj系统的时候,需要使用代码编辑器,决定使用Monaco Editor&#xff0c;但是因为自身能力问题&#xff0c;读不懂官网文档&#xff0c;最终结合ai和网友的帖子成功引入&…