设计模式——命令模式

命令模式

定义

将一个请求封装成一个对象,从而让你使用不同的请求吧客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
命令模式是一个高内聚的模式。

优缺点、应用场景

优点

  1. 类间解耦。调用者与接收者之间没有任何依赖关系。调用者只需要调用execute()方法即可,不需要了解哪个接收者执行。
  2. 可拓展性。
  3. 命令模式结合其他模式会更优秀。例如与责任链模式结合,实现命令族解析任务;结合模板方法模式,可以减少Command子类膨胀问题。

缺点

  1. 类的膨胀问题。如果有N个命令,则子类的数量就为N个,这可能会导致类的膨胀,需要慎重使用。

代码模拟场景

项目组有三个小组需求组、美工组、编码组,客户的每个“命令”都有可能涉及到多个组的响应,使用命令模式一方面接收客户的“命令”,另一方面根据“命令”组合出小组之间的分工。

实验小结

  1. 你永远也不知道用户到底怎么定义他的需求,每次的修改都相当于命令
  2. 如果对于每个命令都需要new来处理,那么每次都需要创建一个场景类,而且是手动的执行命令中的每个细节
  3. 命令模式要求,将一个命令中所有的细节都交给Command的实现类来做,执行命令时由唯一执行人Invoker来执行,而客户的需求只跟Invoker说明,由Invoker发布命令

命令模式

UML图

在这里插入图片描述

部门抽象及部门实体

/*** 抽象组*/
public abstract class Group {// 甲乙双方分开办公,如果要和某个组讨论,首先要找到这个组public abstract void find();// 被要求增加功能public abstract void add();// 被要求删除功能public abstract void delete();// 被要求修改功能public abstract void change();// 被要求给出所有的变更计划public abstract void plan();
}/*** 需求组*/
public class RequirementGroup extends Group {@Overridepublic void find() {System.out.println("找到需求组。。。");}@Overridepublic void add() {System.out.println("客户要求增加一项需求");}@Overridepublic void delete() {System.out.println("客户要求删除一项需求");}@Overridepublic void change() {System.out.println("客户要求修改一项需求");}@Overridepublic void plan() {System.out.println("客户要求需求变更计划");}
}/*** 美工组*/
public class PageGroup extends Group {@Overridepublic void find() {System.out.println("找到美工组。。。");}@Overridepublic void add() {System.out.println("客户要求增加一个页面");}@Overridepublic void delete() {System.out.println("客户要求删除一个页面");}@Overridepublic void change() {System.out.println("客户要求修改一个页面");}@Overridepublic void plan() {System.out.println("客户要求页面变更计划");}
}/*** 代码组*/
public class CodeGroup extends Group {@Overridepublic void find() {System.out.println("找到代码组。。。");}@Overridepublic void add() {System.out.println("客户要求增加一项功能");}@Overridepublic void delete() {System.out.println("客户要求删除一项功能");}@Overridepublic void change() {System.out.println("客户要求修改一项功能");}@Overridepublic void plan() {System.out.println("客户要求代码变更计划");}
}

命令Command抽象与实现

/*** 抽象命令类*/
public abstract class Command {// 定义好三个组,子类可以直接使用protected RequirementGroup requirementGroup = new RequirementGroup();protected PageGroup pageGroup = new PageGroup();protected CodeGroup codeGroup = new CodeGroup();// 只有一个方法:执行public abstract void execute();
}/*** 需求组添加需求的命令*/
public class AddRequirementCommand extends Command {@Overridepublic void execute() {super.requirementGroup.find();super.requirementGroup.add();super.requirementGroup.plan();}
}/*** 需求组添加需求的命令*/
public class DeletePageCommand extends Command {@Overridepublic void execute() {super.pageGroup.find();super.pageGroup.delete();super.pageGroup.plan();}
}

执行人(实施)

/*** 执行者*/
public class Invoker {private Command command;// 客户发出命令public Invoker setCommand(Command command) {this.command = command;// 这个地方自己加的,为了方便设置命令后执行return this;}// 执行客户的命令public void action(){this.command.execute();}
}

入口类

public class CommandMain {public static void main(String[] args) {
//        硬核需求();command();}// 命令模式public static void command(){Invoker<Command> invoker = new Invoker<>();// 添加一个需求Command addRequirementCommand = new AddRequirementCommand();// 设置命令,在这里需要什么命令就直接new一个Command接口的实现类即可Command deletePageCommand = new DeletePageCommand();invoker.setCommand(addRequirementCommand);     // 执行invoker.setCommand(deletePageCommand);invoker.rollback(addRequirementCommand.getClass());     // 客户要求回滚invoker.action();}public static void 硬核需求(){System.out.println("-----客户要求增加一项需求-----");Group requirementGroup = new RequirementGroup();// 找到需求组requirementGroup.find();// 添加需求requirementGroup.add();// 要求变更计划requirementGroup.plan();}
}

结果

非命令模式
在这里插入图片描述

命令模式
在这里插入图片描述

参考书籍

秦小波《设计模式之禅》

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用OpenCV的viz模块创建和控制一个3D可视化窗口

#include <opencv2/viz.hpp> #include <iostream>using namespace cv; using namespace std;int main() {

821. 跳台阶

链接&#xff1a; 821. 跳台阶 - AcWing题库 题目&#xff1a; 一个楼梯共有 nn 级台阶&#xff0c;每次可以走一级或者两级&#xff0c;问从第 00 级台阶走到第 nn 级台阶一共有多少种方案。 输入格式 共一行&#xff0c;包含一个整数 nn。 输出格式 共一行&#xff0c;包含一…

【Linux】ELK 企业级日志分析系统

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 ELK 企业级日志分析系统 ELK 概述1、ELK 简介2、为什么要使用 ELK3、完整日志系统基本特征4、ELK 的工作原理 ELK Elasticsearch 集群部署&#xff08;在Node1、Node2节点上操…

Filebeat+ELK (grok、mutate、mutiline、date)详解

目录 一&#xff1a;FilebeatELK 部署 1&#xff0e;安装 Filebeat 2&#xff0e;设置 filebeat 的主配置文件 3.在 Logstash 组件所在节点上新建一个 Logstash 配置文件 4.访问登录 二&#xff1a;grok 正则捕获插件 1、内置正则表达式调用 2、举例说明 3、自定义表达式…

单元测试与端到端测试——主要区别

目录 前言&#xff1a; 什么是单元测试&#xff1f; 单元测试生命周期 单元测试的好处 那么它有什么好处呢&#xff1f; 单元测试示例 单元测试的类型 单元测试工具 什么是端到端测试&#xff1f; 端到端测试 端到端测试的主要好处是什么&#xff1f; 端到端测试示…

统计年,月,日,java补充无的数据

需求&#xff1a;营收趋势图。需要按年&#xff0c;按月&#xff0c;按日。按年&#xff0c;后方选择日历 起始年-结束年。例如start2013 end 2023 按月&#xff0c;后方选择月份 起始月-结束月。例如start 2022-10 end 2023-07。 按日&#xff0c;后方选择日 起始日-结束日。例…

学术英语UNIT1~UNIT4知识点总结

目录 UNIT 1 1.Deciding on topic --AMI 2.Writing a working title 3.Literacy Skills--Avoiding plagiarism 4.Literacy Skills--citation and referring skills 5.Literacy Skills--quoting 6.Literacy Skills--summarizing UNIT2 1.Academic Writing -searching…

Linux - CentOS 二进制安装 MySQL 8.0.31(非常实用)

一、下载 mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz 下载地址&#xff1a;MySQL :: Download MySQL Community Server (Archived Versions) 具体如下图所示&#xff1a; 二、将 mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz 放入到服务器的 /usr/local &#xff08;路径可…

C# PaddleInference OCR 验证码识别

说明 C# PaddleInference OCR 验证码识别 自己训练的模型&#xff0c;只针对测试图片类型&#xff0c;准确率99% 效果 项目 VS2022.net4.8OpenCvSharp4Sdcb.PaddleInference 测试图片 代码 using OpenCvSharp; using Sdcb.PaddleInference.Native; using Sdcb.PaddleInfer…

设计模式——中介者模式

中介者模式&#xff08;非中介者场景&#xff09; 即没有统一的管理者&#xff0c;需要与其他类交流时就new一个 场景 三个类&#xff1a;采购、销售、库存采购商品时&#xff0c;联系销售看看的销售情况好不好&#xff0c;再决定采购的数量销售负责反馈销售情况&#xff0c…

C++教程——const修饰指针、结构体、文件操作

const修饰指针 常量指针 指针常量 const既修饰指针&#xff0c;又修饰常量 指针与数组 结构体 通过指针访问结构体变量中的数据 结构体中const使用场景 文件操作 写文件 读文件 读取数据的方式 二进制读写文件 写文件 读文件

猿人学第二届第一题找修改位置(非答题)

第二届第一题 AES(魔改) Base64(魔改) MD5 第一题不难&#xff0c;想要得到结果直接扣代码就行&#xff0c;但是我想找找到底修改了哪个位置。 MD5( AES (now page) ) AES加密ECB-pksc7 的 key 标准是128位即 16*8(bit) &#xff0c;这里666yuanrenxue66 是15位不是标准k…