【行为型模式】命令模式

ops/2024/9/23 20:16:27/

一、命令模式概述

        命令模式的定义将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。(对象行为型)

  • 命令模式优缺点
    • 优点
      • 1.类间解耦:调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用Command 抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。
      • 2.可扩展性:Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严 重的代码耦合。
      • 3.命令模式结合其他模式会更优秀:命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少 Command子类的膨胀问题。
    • 缺点
      • 如果有N个命令,问题就出来 了,Command的子类就可不是几个,而是N个,这个类膨胀得非常大。
  • 适用环境
    • 1.需要先将一个函数登记上,然后再以后调用此函数时,就需要使用命令模式,其实这就是回调函数
    • 2.有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。

二、代码实现

        命令模式包含四个角色:

  • Command命令角色(抽象):声明执行命令的接口,拥有执行命令的抽象方法 execute ();
  • ConcreteCommand(具体命令):是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作;
  • Invoker调用者角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
  • Receiver接受者角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者;
        2.1 抽象命令(Command接口)
java">package Command.remoteControl;
//命令接口
public interface Command {//执行命令public void execute();
}
        2.2 具体命令(LightOnCommand、LightOffCommand、NoCommand、StereoOnWithCDCommand、StereoOffCommand)
java">package Command.remoteControl;
//具体命令,接受并执行命令,开灯命令
public class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light){this.light = light;}@Overridepublic void execute() {// TODO Auto-generated method stublight.on();}}
java">package Command.remoteControl;
//具体命令,接受并执行命令,关灯
public class LightOffCommand implements Command {private Light light;public LightOffCommand(Light light){this.light = light;}@Overridepublic void execute() {// TODO Auto-generated method stublight.off();}}
java">package Command.remoteControl;
//具体命令,接受并执行命令,无任何响应命令
public class NoCommand implements Command {@Overridepublic void execute() {// TODO Auto-generated method stub}}
java">package Command.remoteControl;
//具体命令,接受并执行命令,开CD且音量为14
public class StereoOnWithCDCommand implements Command {private Stereo stereo;public StereoOnWithCDCommand(Stereo stereo) {this.stereo = stereo;}@Overridepublic void execute() {// TODO Auto-generated method stubstereo.on();stereo.setCD();stereo.setVolume(14);}}
java">package Command.remoteControl;
//具体命令,接受并执行命令,关音响
public class StereoOffCommand implements Command {private Stereo stereo;public StereoOffCommand(Stereo stereo) {this.stereo = stereo;}@Overridepublic void execute() {// TODO Auto-generated method stubstereo.off();}}
        2.3 Invoker(Light、Stereo)
java">package Command.remoteControl;
//Invoker,发送开关请求,电灯
public class Light {String position;public Light(String position) {this.position = position;}public void on(){System.out.println(position +" light is on...");}public void off(){System.out.println(position+" light is off...");}}
java">package Command.remoteControl;
//Invoker,发送开关音量请求,音响
public class Stereo {String position;public Stereo(String position) {this.position = position;}public void on(){System.out.println(position + " stereo is on...");}public void off(){System.out.println(position + " stereo is off...");}public void setCD() {System.out.println(position+ " stereo is set for CD input...");}public void setVolume(int volume) {System.out.println(position+" stereo volume set to " + volume);}}
         2.4 接收者(RemoteControl)
java">package Command.remoteControl;
//Receiver:干活,遥控器
public class RemoteControl {//开灯private Command[] onCommands;//关灯private Command[] offCommands;public RemoteControl(){//初始化开与关的数组onCommands = new Command[7];offCommands = new Command[7];NoCommand noCommand = new NoCommand();for(int i=0;i<7;i++){onCommands[i] = noCommand;offCommands[i] = noCommand;}}/*** 设置按钮指令* @param position* @param onCommand* @param offCommand*/public void setCommand(int position,Command onCommand, Command offCommand){onCommands[position] = onCommand;offCommands[position] = offCommand;}//按下开或关,硬件就负责调用对应的方法public void onButtonWasPushed(int position) {onCommands[position].execute();}public void offButtonWasPushed(int position) {offCommands[position].execute();}public String toString() {StringBuffer stringBuff = new StringBuffer();stringBuff.append("\n------ Remote Control -------\n");for (int i = 0; i < onCommands.length; i++) {stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName()+ "    " + offCommands[i].getClass().getName() + "\n");}return stringBuff.toString();}}
        2.5 main方法实现命令模式
java">package Command.remoteControl;public class RemoteLoader {public static void main(String[] args) {// TODO Auto-generated method stubRemoteControl remoteControl = new RemoteControl();Light livingRoomLight = new Light("Living Room");LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight); Stereo stereo = new Stereo("Living Room");StereoOnWithCDCommand setreoOnWithCD = new StereoOnWithCDCommand(stereo);StereoOffCommand setreoOff = new StereoOffCommand(stereo);//加载到遥控器槽中remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);remoteControl.setCommand(1, setreoOnWithCD, setreoOff);//打印遥控器插槽和被指定的命令System.out.println(remoteControl);//按遥控器remoteControl.onButtonWasPushed(0);remoteControl.offButtonWasPushed(0);remoteControl.onButtonWasPushed(1);remoteControl.offButtonWasPushed(1);}}
        2.6 UML图

三、代码结构


http://www.ppmy.cn/ops/9949.html

相关文章

npm i 依赖下载失败

git config --global url."https://".insteadOf git://解决npm install 报错 npm ERR code 128 Permission denied_please make sure you have the correct access right-CSDN博客

【UI】element-ui的el-dialog的遮罩层在模态框的前面bug

最近在写element ui 的时候使用dialog组件&#xff0c;偶然出现了这种情况 原因&#xff1a; 是因为遮罩层插入进了body标签下&#xff0c;z-index高于当前父元素。 解决&#xff1a;在el-dialog标签里加上:modal-append-to-body"false"就可以了。 饿了么官网文档&a…

为什么删除node_modules文件夹很慢

在处理Node.js项目时&#xff0c;删除node_modules文件夹常常是一个非常缓慢的过程。这个现象主要由以下几个原因造成&#xff1a; 1. 文件和目录数量庞大 node_modules 文件夹之所以删除缓慢&#xff0c;最直接的原因是它包含了大量的文件和目录。当你通过npm或yarn这样的包…

sqlplus / as sysdba登陆失败,(ORA-01017)

周一上班检查alert log&#xff0c;看到某个库报出大量的错误 提示无法连接到ASM实例&#xff0c;这是某知名MES厂商DBA创建的11G RAC刚刚​转交到我手上的&#xff0c;这又是给我挖了什么坑&#xff1f; 报错为ORA-01017​用户名密码不对&#xff1f;​what&#xff1f; 登陆o…

学习STM32第十六天

RTC实时时钟 一、简介 RTC是一个独立的BCD格式定时器&#xff0c;提供一个时钟日历&#xff0c;两个可编程报警中断&#xff0c;一个具有中断功能周期性可编程唤醒标志&#xff0c;RTC和时钟配置系统处于后备区域。 通过两个32位寄存器以BCD格式实现秒、分钟、小时&#xff08…

Rust实战 | 用 RustRover 开发猜数字游戏

#1、概述 从这期开始&#xff0c;我会以实际项目的形式&#xff0c;分享个人学习 Rust 语言的过程。期间&#xff0c;我不会讲太多语法知识&#xff0c;需要各位看官自行查阅文档&#x1f604;。 开始前&#xff0c;需具备 Rust 环境&#xff08;我用的是当前最新版本1.77.2&…

Selenium(一):八大元素定位

元素定位八大方法 1、find_element_by_id 通过id定位 find_element(By.ID,"kw") #建议使用2、find_element_by_name 通过标签名定位 find_element(By.NAME,"wd") #建议使用3、find_element_link_text 通过链接文本定位 find_element(By.LINK_TEXT,&q…

【NLP练习】使用Word2Vec实现文本分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、数据预处理 1. 任务说明 本次加入Word2Vec使用PyTorch实现中文文本分类&#xff0c;Word2Vec则是其中的一种词嵌入方法&#xff0c;是一种用于生成词向量…