命令模式介绍

news2024/11/15 20:36:41

目录

一、命令模式介绍

1.1 命令模式定义

1.2 命令模式原理

1.2.1 命令模式类图

1.2.2 模式角色说明

二、命令模式的应用

2.1 需求说明

2.2 需求实现

2.2.1 抽象命令接口

2.2.2 订单类

2.2.3 厨师类

2.2.4 服务员类

2.2.5 具体命令类

2.2.6 测试类

三、命令模式总结

3.1 命令模式的优点

3.2 命令模式的缺点

3.3 命令模式的使用场景


一、命令模式介绍

1.1 命令模式定义

命令模式(command pattern)的定义: 命令模式将请求(命令)封装为一个对象,这样可以使用不同的请求参数化其他对象(将不同请求依赖注入到其他对象),并且能够支持请求(命令)的排队执行、记录日志、撤销等 (附加控制)功能。

命令模式的核心是将指令信息封装成一个对象,并将此对象作为参数发送给接收方去执行,达到使命令的请求与执行方解耦,双方只通过传递各种命令对象来完成任务。
在实际的开发中,如果你用到的编程语言并不支持用函数作为参数来传递,那么就可以借助命令模式将函数封装为对象来使用。

我们知道,C语言支持函数指针,我们可以把函数当作变量传递来传递去。但是,在大部分编程语言中,函数没法儿作为参数传递给其他函数,也没法儿赋值给变量。借助命令模式,我们可以将函数封装成对象。具体来说就是,设计一个包含这个函数的类,实例化一个对象传来传去,这样就可以实现把函数像对象一样使用。

1.2 命令模式原理

1.2.1 命令模式类图

1.2.2 模式角色说明

命令模式包含以下主要角色:

  • 抽象命令类(Command)角色: 定义命令的接口,声明执行的方法。
  • 具体命令(Concrete Command)角色:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
  • 实现者/接收者(Receiver)角色: 接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
  • 调用者/请求者(Invoker)角色: 要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。

二、命令模式的应用

2.1 需求说明

模拟酒店后厨的出餐流程,来对命令模式进行一个演示,命令模式角色的角色与案例中角色的对应关系如下:

  1. 服务员: 即调用者角色,由她来发起命令。
  2. 厨师: 接收者,真正执行命令的对象。
  3. 订单: 命令中包含订单。

2.2 需求实现

2.2.1 抽象命令接口

package main.java.cn.test.command.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/15 17:42:27
 * @description 抽象命令接口
 */
public interface Command {
    //只需要定义一个统一的执行方法
    void execute();
}

2.2.2 订单类

package main.java.cn.test.command.V1;

import java.util.HashMap;
import java.util.Map;

/**
 * @author ningzhaosheng
 * @date 2024/1/15 17:40:57
 * @description 订单类
 */
public class Order {
    //餐桌号码
    private int diningTable;
    //存储菜名与份数
    private Map<String, Integer> foodMenu = new HashMap<>();

    public int getDiningTable() {
        return diningTable;
    }

    public void setDiningTable(int diningTable) {
        this.diningTable = diningTable;
    }

    public Map<String, Integer> getFoodMenu() {
        return foodMenu;
    }

    public void setFoodDic(Map<String, Integer> foodMenu) {
        this.foodMenu = foodMenu;
    }

}

2.2.3 厨师类

package main.java.cn.test.command.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/15 17:41:47
 * @description 厨师类 -> Receiver角色
 */
public class Chef {
    public void makeFood(int num, String foodName) {
        System.out.println(num + "份," + foodName);
    }
}

2.2.4 服务员类

package main.java.cn.test.command.V1;

import java.util.ArrayList;

/**
 * @author ningzhaosheng
 * @date 2024/1/15 17:44:20
 * @description 服务员-> Invoker调用者
 */
public class Waiter {
    //可以持有很多的命令对象
    private ArrayList<Command> commands;

    public Waiter() {
        commands = new ArrayList();
    }

    public Waiter(ArrayList<Command> commands) {
        this.commands = commands;
    }

    public void setCommands(Command command) {
        commands.add(command);
    }

    //发出命令 ,指挥厨师工作
    public void orderUp() {
        System.out.println("服务员: 叮咚,有新的订单,请厨师开始制作......");
        for (Command cmd : commands) {
            if (cmd != null) {
                cmd.execute();
            }
        }
    }
}

2.2.5 具体命令类

package main.java.cn.test.command.V1;

import java.util.Set;

/**
 * @author ningzhaosheng
 * @date 2024/1/15 17:42:55
 * @description 具体命令
 */
public class OrderCommand implements Command {
    //持有接收者对象
    private Chef receiver;
    private Order order;

    public OrderCommand(Chef receiver, Order order) {
        this.receiver = receiver;
        this.order = order;
    }


    @Override
    public void execute() {
        System.out.println(order.getDiningTable() + "号桌的订单: ");
        Set<String> keys = order.getFoodMenu().keySet();
        for (String key : keys) {
            receiver.makeFood(order.getFoodMenu().get(key), key);
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(order.getDiningTable() + "号桌的菜已上齐.");
    }
}

2.2.6 测试类

package main.java.cn.test.command.V1;

/**
 * @author ningzhaosheng
 * @date 2024/1/15 17:45:22
 * @description 测试类
 */
public class Test {
    public static void main(String[] args) {
        Order order1 = new Order();
        order1.setDiningTable(1);
        order1.getFoodMenu().put("鲍鱼炒饭", 1);
        order1.getFoodMenu().put("茅台迎宾", 1);
        Order order2 = new Order();
        order2.setDiningTable(3);
        order2.getFoodMenu().put("海参炒面", 1);
        order2.getFoodMenu().put("五粮液", 1);
        //创建接收者
        Chef receiver = new Chef();
        //将订单和接收者封装成命令对象
        OrderCommand cmd1 = new OrderCommand(receiver, order1);
        OrderCommand cmd2 = new OrderCommand(receiver, order2);
        //创建调用者
        Waiter invoke = new Waiter();
        invoke.setCommands(cmd1);
        invoke.setCommands(cmd2);
        //将订单发送到后厨
        invoke.orderUp();
    }
}

三、命令模式总结

3.1 命令模式的优点

  • 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
  • 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
  • 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。

3.2 命令模式的缺点

  • 使用命令模式可能会导致某些系统有过多的具体命令类。
  • 系统结构更加复杂。

3.3 命令模式的使用场景

  • 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
  • 系统需要在不同的时间指定请求、将请求排队和执行请求。
  • 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。

好了,本次分享就到这里,欢迎大家继续阅读《设计模式》专栏其他设计模式内容,如果有帮助到大家,欢迎大家点赞+关注+收藏,有疑问也欢迎大家评论留言!

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

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

相关文章

Ubuntu20.04输入法异常导致的黑屏:fcitx和ibus输入法的卸载与安装

Ubuntu20.04输入法异常导致的黑屏&#xff1a;fcitx和ibus输入法的卸载与安装_ubuntu卸载fcitx-CSDN博客 问题背景 系统&#xff1a;Ubuntu20.04 由于fcitx的不完整配置&#xff0c;导致fcitx输入法无法正常工作。决心卸载所有输入法&#xff0c;重新安装。但是由于在没有完整…

C#使用DateAndTime.DateDiff方法计算年龄

目录 一、计算年龄的方法 二、 DateAndTime类 1.定义 2.常用方法 3.DateDiff(DateInterval, DateTime, DateTime, FirstDayOfWeek, FirstWeekOfYear) 三、使用DateAndTime.DateDiff方法计算年龄 一、计算年龄的方法 使用DateDiff方法计算系统时间与员工生日之间相隔的年…

python-自动篇-办公-用Excel画画

文章目录 代码所遇问题ModuleNotFoundError: No module named xlsxwriterFileNotFoundError: [Errno 2] No such file or directory: 111.jpg 效果附件图片excel 代码 # coding: utf-8from PIL import Image from xlsxwriter.workbook import Workbookclass ExcelPicture(obje…

linux性能优化-磁盘I_O优化

1.文件系统 1.1.文件系统的工作原理 文件系统是在磁盘的基础上&#xff0c;提供了一个用来管理文件的树状结构。 接下来我们就看看Linux 文件系统的工作原理。 1.1.1索引节点和目录项 在 Linux 中一切皆文件 ,文件系统,本身是对存储设备上的文件&#xff0c;进行组织管理的…

TDSQL-PG高可用原理与方案设计

笔记主要是把架构具像化到机架图上。 TDSQL-PG的高可用方案主要通过每个部件的多副本冗余来实现&#xff0c;当一个部件的主部件出现故障不可恢复&#xff0c;系统将会自动重新选出对应的备份部件取代原来的主部件。而强同步复制是在节点级保证每个节点的主从数据完全一致&…

Facebook的区块链之路:探秘数字货币的未来

近年来&#xff0c;Facebook一直在积极探索区块链技术&#xff0c;并逐渐将目光聚焦在数字货币领域。从推出Libra项目到改名为Diem&#xff0c;Facebook一直在寻求在数字货币领域取得突破性进展。本文将深入探讨Facebook的区块链之路&#xff0c;揭示其对数字货币未来发展的影响…

Web开发:新建一个WebAPI的demo

一、新建一个api项目&#xff0c;并设置为启动项目 二、控制器目录新建一个控制器&#xff0c;命名为TestController&#xff0c;并且添加如下代码 添加后 代码&#xff1a; using Microsoft.AspNetCore.Mvc;namespace WebApplication1.Controllers {public class TestControl…

【Electron】Electron是什么

1. Electron是什么 Electron是使用JavaScript、HTML和CSS构建跨平台&#xff08;Windows、MacOs、Linux&#xff09;的桌面应用。Electron其实就是一个可以展示网页内容的壳子&#xff0c;相当于一个独立的浏览器&#xff0c;可以提供给你一些接口&#xff0c;去调用系统的资源…

电脑 wifi 常断

问题 电脑wifi网络经常断。 详细问题 笔者使用笔记本电脑&#xff0c;发现每过三五分钟&#xff0c;wifi便会自动断开。 解决方案 步骤1、搜索框搜索设备管理器。 步骤2、找到网络适配器并点击。 步骤2、找到网络适配器菜单中的Wireless相关内容&#xff0c;右键&#x…

超优秀的三维模型轻量化、格式转换、可视化部署平台!

1、基于 HTML5 和 WebGL 技术&#xff0c;可在主流浏览器上进行快速浏览和调试&#xff0c;支持PC端和移动端 2、自主研发 AMRT 展示框架和9大核心技术&#xff0c;支持3D模型全网多端流畅展示与交互 3、提供格式转换、减面展UV、烘焙等多项单模型和倾斜摄影模型轻量化服务 4、…

计算机毕业设计 基于SpringBoot的律师事务所案件管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

从 Vscode 中远程连接 WSL 服务器:可以本地操作虚拟机

从 Vscode 中远程连接 WSL 服务器&#xff1a;可以本地操作虚拟机 1.下载 Vscode Visual Studio Code - Code Editing. Redefined 2.搜索框中输入>wsl&#xff0c;点击 WSL&#xff1a;Connect to WSL using Distro... 3.点击下载好的Ubuntu&#xff0c;当左下角出现图片同…

Maven《四》-- 基于Idea进行Maven工程构建

目录 &#x1f436;4.1 构建概念和构建过程 &#x1f436;4.2 命令方式项目构建 1. &#x1f959;编译&#xff1a;mvn compile 2. &#x1f959;清理&#xff1a;mvn clean 3. &#x1f959;打包&#xff1a;mvn package 4. &#x1f959;安装&#xff1a;mvn install …

51单片机1-6

目录 单片机介绍 点亮一个LED 流水灯参考代码 点亮流水LEDplus版本 独立按键 独立按键控制LED亮灭 静态数码管 静态数码管显示 动态数码管显示 模块化编程 调试工具 矩阵键盘 矩阵键盘显示数据 矩阵键盘密码锁 学习B站江协科技课程笔记。 安装keil&#xff0c;下…

dubbo:深入理解Apache Dubbo与实战

dubbo核心组件 层次名 作 用 Service 业务层。包括业务代码的接口与实现&#xff0c;即开发者实现的业务代码 config 配置层。主要围绕ServiceConfig &#xff08;暴露的服务配置&#xff09;和ReferenceConfig &#xff08;引用的服务配置&#xff09;两个实现类展开&#xf…

NetSuite 文心一言(Ernie)的AI应用

有个故事&#xff0c;松下幸之助小时候所处的年代是明治维新之后&#xff0c;大量引用西洋技术的时期。当时大家对“电”能干什么事&#xff0c;充满好奇。“电能干什么&#xff1f;它能帮我们开门么&#xff1f;” 松下幸之助的爷爷对电不屑&#xff0c;于是就问他。松下幸之助…

ORBSLAM3安装

0. C11 or C0x Compiler sudo apt-get install gccsudo apt-get install gsudo apt-get install build-essentialsudo apt-get install cmake1. 依赖 在该目录终端。 1. 1.Pangolin git clone https://github.com/stevenlovegrove/Pangolin.git sudo apt install libglew-d…

Java实现超市账单管理系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统设计3.1 总体设计3.2 前端设计3.3 后端设计在这里插入图片描述 四、系统展示五、核心代码5.1 查询供应商5.2 查询商品5.3 新增超市账单5.4 编辑超市账单5.5 查询超市账单 六、免责说明 一、摘要 1.1 项目介绍 基于…

1、Seaborn可视化库

你的数据可视化编程初体验! Seaborn是一个基于matplotlib的图形可视化Python库,它提供了一种高级的API接口,使得制作统计图形更加容易。 Seaborn的目标是使可视化成为探索和理解数据的核心部分,它面向数据集的绘图功能对整个数据集进行操作,并在内部执行必要的语义映射和统…

土堆学习笔记——P29完整的模型训练套路(三)

一些细节&#xff1a; 在训练前 有一个tudui.train()的作用&#xff1a; 如果网络里有dropout/batchnorm等层&#xff0c;就需要用到tudui.train()&#xff0c;也就是没有这些层的话&#xff0c;tudui.train()没用调用不调用都行 在测试前 有一个tudui.eval()的作用&#xff1…