Head First Design Patterns - 命令模式

什么是命令模式

命令模式,把请求封装成对象,以便使用不同的请求、队列或者日志请求来参数化其他对象,并支持可撤回的操作。

为什么会有命令模式

假设要设置一个遥控器,遥控器需要控制多个设备,每个设备除了开关,可能还会有属于自己的一些特定的函数,如下图所示:
在这里插入图片描述
如果按照常规的设计思路,遥控器中需要包含很多if … else判断,且每次新增设备,都需要入侵到遥控器内部代码中修改,这是一个糟糕的设计,

命令模式的特点

命令模式能把动作的请求者,从实际执行动作的对象解耦。通过在设计中引入命令对象,把一些事情(像开灯)封装成一个特定对象。

如果按下遥控器,遥控器会请求命令对象去做一些事情,遥控器并不知道实际的工作内容是什么。这就相当于把遥控器和灯解耦了。

当你需要把做出请求的对象,从知道如何执行请求的对象解耦时候,可以使用命令模式。

命令模式的类图

在这里插入图片描述

代码案例

  1. Command接口
public interface Command {
    public void execute();

    public void undo();
}
  1. 设备类
public class Light {
    private String name;
    public void on() {
        System.out.println("light on");
    }

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

    public Light(String name) {
        this.name = name;
    }
}
  1. 命令对象-关灯
public class LightOffCommand implements Command{
    Light light;

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

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

    @Override
    public void undo() {
        light.on();
    }
}
  1. 命令对象-开灯
public class LightOnCommand implements Command {
    Light light;

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

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

    @Override
    public void undo() {
        light.off();
    }
}
  1. 命令对象-空对象
public class NoCommand implements Command{
    @Override
    public void execute() {

    }

    @Override
    public void undo() {

    }
}

空对象经常在设计模式中用到,可以免除对null的判断

  1. 命令的接受者-相当于遥控器类
public class RemoteControllerWithUndo {
    Command[] onCommands;
    Command[] offCommands;
    Command undoCommand;

    public RemoteControllerWithUndo() {
        onCommands = new Command[7];
        offCommands = new  Command[7];

        Command noCommand = new NoCommand();

        for (int i = 0; i < 7; i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }

        undoCommand = noCommand;
    }

    public void setCommands(int slot, Command onCommand, Command offCommand) {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }

    public void onButtonWasPushed(int slot) {
        onCommands[slot].execute();
        undoCommand = onCommands[slot];
    }

    public void offButtonWasPushed(int slot) {
        offCommands[slot].execute();
        undoCommand = offCommands[slot];
    }

    public void undoButtonWasPushed() {
        undoCommand.undo();
    }

    @Override
    public String toString() {
        StringBuffer stringBuffer = new StringBuffer();

        stringBuffer.append("\n --- Remote Control --- \n");
        for (int i = 0; i < onCommands.length; i++) {
            stringBuffer.append("[slot " + i + "] " + onCommands[i].getClass().getName()
            + " " + offCommands[i].getClass().getName() + "\n");
        }

        return stringBuffer.toString();
    }
}
  1. 命令的调用者
public class RemoteLoader {
    public static void main(String[] args) {
        RemoteControllerWithUndo remoteControllerWithUndo = new RemoteControllerWithUndo();

        Light livingRoomLight = new Light("living Room");

        LightOnCommand livingOnCommand = new LightOnCommand(livingRoomLight);
        LightOffCommand lightOffCommand = new LightOffCommand(livingRoomLight);

        remoteControllerWithUndo.setCommands(0, livingOnCommand, lightOffCommand);

        remoteControllerWithUndo.onButtonWasPushed(0);
        remoteControllerWithUndo.offButtonWasPushed(0);

        System.out.println(remoteControllerWithUndo);

        remoteControllerWithUndo.undoButtonWasPushed();
    }
}
  1. 结果
    在这里插入图片描述

命令模式的应用

请求队列、日志请求

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MS30517SA单通道、高速、低侧栅极驱动器

产品简述 MS30517SA 是单通道、高速、低侧栅极驱 动器器件&#xff0c;能够有效地驱动 MOSFET 和 IGBT 开 关 。 芯片的 设 计 能 够 大 大 减 少 击 穿 电 流 &#xff0c; MS30517SA 能够提供高峰值拉、灌电流脉冲&#xff0c; 同时提供了轨到轨驱动能力以及低传播…

C break 语句

C 语言中 break 语句有以下两种用法&#xff1a; 当 break 语句出现在一个循环内时&#xff0c;循环会立即终止&#xff0c;且程序流将继续执行紧接着循环的下一条语句。它可用于终止 switch 语句中的一个 case。 如果您使用的是嵌套循环&#xff08;即一个循环内嵌套另一个循…

自动驾驶---Motion Planning之构建SLT Driving Corridor

1 背景 在上篇博客《自动驾驶---Motion Planning之Speed Boundary》中,主要介绍了Apollo中Speed Boundary的一些内容,可以构造ST图得到边界信息,最后结合粗糙的速度曲线和路径曲线,即可使用优化的方法求解得到最终的轨迹信息(s,s,s,l,l,l)。 本篇博客笔者主要介绍近…

Matlab 字符串相关命令

参考 字符串命令汇总1

代码随想录算法训练营第四十一天|卡码网46. 携带研究材料(第六期模拟笔试)、416. 分割等和子集

卡码网46. 携带研究材料&#xff08;第六期模拟笔试&#xff09; 刷题https://kamacoder.com/problempage.php?pid1046 题解&#xff1a; 一维背包 文章讲解https://programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-2.html…

js导出的excel文件无法打开/打开乱码,excel无法打开xxx.xlsx因为文件格式或文件扩展无效

excel无法打开xxx.xlsx因为文件格式或文件扩展无效 使用 a 标签导出这里就不细说了&#xff0c;直接说上述问题解决方案 在调用导出接口的时候加上两个参数 responseType: “blob” responseEncoding: “utf8” export function test(data) {return util({url: /test,method: …

制冷系统管道焊接气焊安全操作

气焊操作安全教育&#xff1a; 1、检查气焊用具完好牢固无损&#xff0c;不得贴粘有&#xff08;机油&#xff09;&#xff1b; 2、气瓶余压&#xff08;2KG&#xff09;停止使用&#xff1b;清除动火 10 米范围内易燃易爆物料&#xff1b; 3、库房内动火要 做好通风排气&…

数据结构——二叉树的遍历【前序、中序、后序】

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

【精选】30+Redis面试题整理(2024)附答案

目录 前言Redis基础项目有用到redis吗&#xff1f;你们项目为什么用redis?redis为什么这么快&#xff1f;了解Redis的线程模型吗&#xff1f;Redis优缺点?redis如何实现持久化&#xff1f;RDB持久化过程&#xff1f;AOF持久化过程&#xff1f;AOF持久化会出现阻塞吗&#xff…

svn安装与汉化(svn1.14.5版本)带汉化包

安装 下载 TortoiseSVN 去官网下载 TortoiseSVN&#xff0c;找到页面底部 TortoiseSVN 下载&#xff0c;选择适用自己电脑位数的 TortoiseSVN 客户端下载&#xff1a; 或者 链接&#xff1a;https://pan.baidu.com/s/1YSw9LalULsQecOQgFrXGSQ?pwd4ds7 提取码&#xff1a;4ds…

套接字编程 --- 三

目录 1. 前置性知识 1.1. listen 系统调用 1.2. accept 系统调用 1.3. 如何通信 1.3.1. read 系统调用 && write系统调用 1.3.2. recv 系统调用 && send 系统调用 2. TCP --- demo 2.1. Tcp_Server.hpp (version 1) 2.2. Tcp_Server.hpp (version 2…

【存储】ZYNQ+NVMe小型化全国产存储解决方案

文章目录 1、背景2、基础理论3、设计方案3.1、FPGA设计方案3.1.1、NVMe控制器实现3.1.2、NVMe控制器实现 3.2 驱动软件设计方案3.2.1 读写NVMe磁盘软件驱动3.2.2 NVMe磁盘驱动设计3.2.3 标准EXT4文件系统设计 3.3 上位机控制软件设计方案 4、测试结果4.1 硬件测试平台说明4.2 测…

【鸿蒙 HarmonyOS 4.0】Web组件

一、介绍 页面加载是Web组件的基本功能。根据页面加载数据来源可以分为三种常用场景&#xff0c;包括加载网络页面、加载本地页面、加载HTML格式的富文本数据。 二、加载网页 2.1、加载在线网页 Web组件的使用非常简单&#xff0c;只需要在Page目录下的ArkTS文件中创建一个…

Python 导入Excel三维坐标数据 生成三维曲面地形图(面) 1、线条折线曲面

环境和包: 环境 python:python-3.12.0-amd64包: matplotlib 3.8.2 pandas 2.1.4 openpyxl 3.1.2 代码: import pandas as pd import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D from matplotlib.colors import ListedColo…

基于Python3的数据结构与算法 - 15 栈和队列的应用(迷宫问题)

题目 给一个二维列表&#xff0c;表示迷宫&#xff08;0表示通道&#xff0c;1表示围墙&#xff09;。给出算法&#xff0c;求一条走出迷宫的路径。 方法一 &#xff1a;使用栈 -- 深度优先搜索 方法&#xff1a;回溯法 思路&#xff1a;从一个节点开始&#xff0c;任意找下…

OpenCV开发笔记(七十七):相机标定(二):通过棋盘标定计算相机内参矩阵矫正畸变摄像头图像

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/136616551 各位读者&#xff0c;知识无穷而人力有穷&#xff0c;要么改需求&#xff0c;要么找专业人士&#xff0c;要么自己研究 红胖子(红模仿)的博…

基于Java+SpringBoot+vue+element实现汽车订票管理平台详细设计和实现

基于JavaSpringBootvueelement实现汽车订票管理平台详细设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 …

开源好用的所见即所得(WYSIWYG)编辑器:Editor.js

文章目录 特点基于区块干净的数据 界面与交互插件标题和文本图片列表Todo表格 使用安装创建编辑器实例配置工具本地化自定义样式 今天介绍一个开源好用的Web所见即所得(WYSIWYG)编辑器&#xff1a; Editor.js Editor.js 是一个基于 Web 的所见即所得富文本编辑器&#xff0c;它…

【毕设级项目】基于AI技术的多功能消防机器人(完整工程资料源码)

基于AI技术的多功能消防机器人演示效果 竞赛-基于AI技术的多功能消防机器人视频演示 前言 随着“自动化、智能化”成为数字时代发展的关键词&#xff0c;机器人逐步成为社会经济发展的重要主体之一&#xff0c;“机器换人”成为发展的全新趋势和时代潮流。在可预见的将来&#…

鸿蒙App基础

基础说明 .1、应用模型 .1.1、构成要素 应用组件 应用组件是应用的基本组成单位&#xff0c;是应用的运行入口。用户启动、使用和退出应用过程中&#xff0c;应用组件会在不同的状态间切换&#xff0c;这些状态称为应用组件的生命周期。应用组件提供生命周期的回调函数&…