当前位置: 首页 > news >正文

命令模式(行为型)

目录

一、前言

二、命令模式

三、总结


一、前言

        命令模式(Command Pattern)是一种行为型设计模式,命令模式将一个请求封装为一个对象,从而可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 

        命令模式由以下角色组成:

Command(命令):

该角色定义了执行操作的接口。通常包含一个执行操作的方法,如 execute()。命令对象可能会携带执行操作所需的参数。

Concrete Command(具体命令):

该角色实现了命令接口,对具体的操作进行了实现。具体命令对象将一个接收者对象绑定到一个动作,并负责调用接收者的相应方法来执行请求。

Receiver(接收者):

该角色实际执行操作的对象。命令对象会将请求委托给接收者来执行实际的操作。

Invoker/Client(调用者/客户端):

该角色创建命令对象并将其发送给接收者。调用者不需要了解命令是如何执行的,它只需要发送请求。

        整个命令模式的结构图:

二、命令模式

        比如在餐馆就餐,我们会先向服务员点单,下单后服务员通知后厨进行制作,这种就可以用命令模式进行演示。Receiver可以当做是具体制作食物的厨师,Invoker可以当做是服务员进行调用,Command理解成每一个菜单,也就是发出的命令。

        先创建厨师Receiver类:

public class Receiver {public void actionOne(){System.out.println("制作食物one");}public void actionTwo(){System.out.println("制作食物two");}public void actionThree(){System.out.println("制作食物three");}
}

        创建抽象命令Command:

public interface Command {void execute();
}

        创建菜单具体的命令:

public class ConcreteCommandOne implements Command{private Receiver receiver;public ConcreteCommandOne(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.actionOne();}
}public class ConcreteCommandTwo  implements Command{private Receiver receiver;public ConcreteCommandTwo(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.actionTwo();}
}public class ConcreteCommandThree  implements Command{private Receiver receiver;public ConcreteCommandThree(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.actionThree();}
}

        创建服务员Invoker类:

public class Invoker {private List<Command> commands = new ArrayList<>();public void setCommand(Command command){commands.add(command);}public void removeCommand(Command command){commands.remove(command);System.err.println("取消订单");}public void call(){for (Command command : commands){command.execute();}}
}

        客户端调用类:

public class Client {public static void main(String[] args) {Receiver receiver = new Receiver();Command commandOne = new ConcreteCommandOne(receiver);Command commandTwo = new ConcreteCommandTwo(receiver);Command commandThree = new ConcreteCommandThree(receiver);Invoker invoker = new Invoker();invoker.setCommand(commandOne);invoker.setCommand(commandTwo);invoker.setCommand(commandThree);invoker.removeCommand(commandTwo);invoker.call();}
}

        执行结果:

        可以看出client创建不同的命令,通过invoker将命令设置进去,也可以通过invoker取消命令,最后invoker通知进行调用。

三、总结

        优点与缺点:

优点:

解耦请求发送者和接收者:

命名模式将请求封装成一个对象,使得发送者和接收者之间的解耦程度增加。发送者只需要知道如何发送命令,而不需要了解命令是如何被执行的。

支持撤销和重做操作:

由于命令对象封装了对接收者的调用,因此可以轻松地实现撤销和重做操作,只需保留历史命令对象即可。

增加新的命令:

通过添加新的命令类,可以轻松地扩展命令模式,而无需修改现有的客户端代码。

支持组合命令:

可以通过组合多个命令对象来执行复杂的操作,从而实现更高级的功能。

缺点:

类爆炸:

在系统中可能会产生大量的具体命令类,如果命令种类过多,可能会导致类爆炸,增加系统的复杂性。

增加调试难度:

由于命令模式涉及多个对象之间的交互,因此调试可能会变得更加复杂。

        应用场景:

GUI应用程序:

命令模式常用于实现菜单和工具栏按钮的操作。每个菜单项或按钮可以表示一个命令,当用户点击时,该命令将被执行。

任务队列:

命令模式可以用于实现任务队列,例如,在操作系统中,可以将用户的操作封装成命令对象,然后将它们放入队列中以便逐个执行。

日志系统:

命令模式可以用于实现日志系统,将所有操作封装成命令对象,并在执行时记录相关的日志信息。

撤销/重做功能:

命令模式很适合实现撤销和重做功能,因为每个命令对象都可以保存执行时的状态,从而支持撤销和重做操作。

相关文章:

  • spring分析工具_springboot startup analyze的部署和使用
  • 「vue同一个组件,不同路由切换时界面没有更新问题」
  • mysql - 为什么MySQL不建议使用NULL作为列默认值?
  • git仓库迁移
  • 【Linux】操作系统之冯诺依曼体系
  • 用HAL库改写江科大的stm32入门-6-3 PWM驱动LED呼吸灯
  • html中 table的 colspan和rowspan
  • 使用Golang调用腾讯云邮件模版发送邮件
  • SpringCloud学习笔记(一)
  • 日有所思的梦想
  • 探索python数据可视化的奥秘:打造专业绘图环境
  • 【全开源】JAVA情侣扭蛋机情侣游戏系统源码支持微信小程序+微信公众号+H5
  • Oracle中rman的增量备份使用分享
  • vue3 前端实现导出下载pdf文件
  • AI实时免费在线图片工具3:人物换脸、图像编辑
  • ➹使用webpack配置多页面应用(MPA)
  • C++入门教程(10):for 语句
  • Docker下部署自己的LNMP工作环境
  • echarts花样作死的坑
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • JavaScript类型识别
  • JavaScript设计模式系列一:工厂模式
  • java小心机(3)| 浅析finalize()
  • JS题目及答案整理
  • Laravel 中的一个后期静态绑定
  • MaxCompute访问TableStore(OTS) 数据
  • mysql innodb 索引使用指南
  • node.js
  • PaddlePaddle-GitHub的正确打开姿势
  • PHP变量
  • Python利用正则抓取网页内容保存到本地
  • uni-app项目数字滚动
  • 程序员该如何有效的找工作?
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 如何在GitHub上创建个人博客
  • 使用agvtool更改app version/build
  • 双管齐下,VMware的容器新战略
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • 第二十章:异步和文件I/O.(二十三)
  • 容器镜像
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • #{}和${}的区别?
  • #window11设置系统变量#
  • (2022 CVPR) Unbiased Teacher v2
  • (70min)字节暑假实习二面(已挂)
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (十八)SpringBoot之发送QQ邮件
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转)jQuery 基础