Java实现命令模式

server/2025/1/11 22:56:59/

一、简介

1、定义和原理

  命令模式(Command Pattern)是一种行为设计模式,将请求(命令)封装成对象,可以用不同的请求封装不同的请求接受者,从而命令不同的接受者执行相应操作;也可以用不同的请求,调用命令对象的不同方法,实现命令对象参数化。通过定义命令接口和具体命令类,将请求封装为对象,并将其传递给调用者。

2、命令模式的结构

命令模式涉及以下几个角色:
Receiver(接收者):命令接受者,处理命令(请求)。
Command(命令):命令接口。
ConcreteCommand(具体命令):将一个请求绑定于一个接受者,调用接收者的相应操作,以实现execute操作。
Invoker(调用者):封装命令执行对应请求。
Client(客户):创建具体命令对象并设定其接收者,用调用者进行调用。

3、优缺点

(1)优点
  • 解耦:发送者和接收者解耦。
  • 灵活性:可以动态地创建、撤销请求。
(2)缺点
  • 增加类的数量:具体命令或者命令接受者需要一个单独的类来实现,这可能会导致类的数量增加。
  • 复杂性:对于简单的操作,使用命令模式可能会显得过于复杂。

二、Java实现案例

1、操作系统命令实现案例

接受者:

java">/*** @Description: 接受者* @Date: 2025-01-08 9:29* @Author: gaoyufei**/
public class Receiver {public void receive(String command){System.out.println("操作系统接受命令:"+command);}
}

命令接口:

java">/*** @Description: 命令接口* @Date: 2025-01-08 9:30* @Author: gaoyufei**/
public interface Command {void execute(String command);void setReceiver(Receiver receiver);
}

具体命令:

java">/*** @Description: 命令接口实现 具体命令* @Date: 2025-01-08 9:31* @Author: gaoyufei**/
public class ConcreteCommand implements Command {private Receiver receiver;public void setReceiver(Receiver receiver){this.receiver=receiver;}@Overridepublic void execute(String command) {receiver.receive(command);}
}

调用者:

java">/*** @Description: 调用者* @Date: 2025-01-08 9:33* @Author: gaoyufei**/
public class Invoke {private Command command;public void setCommand(Command command) {this.command = command;}public void invoke(String command){this.command.execute(command);}
}

客户端:

java">/*** @Description: 客户端* @Date: 2025-01-08 9:34* @Author: gaoyufei**/
public class Client {public static void main(String[] args) {Receiver receiver=new Receiver();Command command=new ConcreteCommand();command.setReceiver(receiver);Invoke invoke=new Invoke();invoke.setCommand(command);invoke.invoke("打开文件");invoke.invoke("关闭文件");}
}

2、领导命令员工完成任务案例

客户端:任务板
命令:任务
调用者:领导
接受者: 员工
员工和领导都要注册在任务板上,领导操作任务板,将任务和员工关联,发布任务。

java">/*** @Description: 员工* @Date: 2025-01-08 10:04* @Author: gaoyufei**/
public class Employee {private String name;public Employee(String name){this.name=name;}public void receiveTask(String task){System.out.println(this.name+"接受任务:"+task);}
}
/*** @Description: 命令接口* @Date: 2025-01-08 10:06* @Author: gaoyufei**/
public interface Command {void setEmployee(Employee employee);void execute(String task);
}/*** @Description: 命令实现,任务* @Date: 2025-01-08 10:07* @Author: gaoyufei**/
public class Task implements Command{private Employee employee;@Overridepublic void setEmployee(Employee employee) {this.employee=employee;}@Overridepublic void execute(String task) {this.employee.receiveTask(task);}
}/*** @Description: 领导* @Date: 2025-01-08 10:11* @Author: gaoyufei**/
public class Leader {private Command command;public void setCommand(Command command){this.command=command;}//发布任务public void issueTask(String task){this.command.execute(task);}
}/*** @Description: 任务板* @Date: 2025-01-08 10:17* @Author: gaoyufei**/
public class TaskBoard {public static void main(String[] args) {Command task=new Task();Leader leader=new Leader();//给张三布置任务:实现产品列表分页功能Employee employee1=new Employee("张三");task.setEmployee(employee1);leader.setCommand(task);leader.issueTask("实现产品列表分页功能");//给张三布置任务:实现产品列表删除功能Employee employee2=new Employee("李四");task.setEmployee(employee2);leader.setCommand(task);leader.issueTask("实现产品列表删除功能");}
}

3、值日委员安排值日生任务案例

客户端:值日板
命令:任务
调用者:卫生委员
接受者: 值日生
卫生委员,在值日板写谁是值日生,谁做什么任务

java">/*** @Description: 值日生* @Date: 2025-01-09 8:39* @Author: gaoyufei**/
public class DutyStudent {private String name;public DutyStudent(String name){this.name=name;}public void receiveTask(String task){System.out.println(this.name+":"+task);}
}/*** @Description: 命令接口* @Date: 2025-01-09 8:41* @Author: gaoyufei**/
public interface Command {void setDutyStudent(DutyStudent dutyStudent);void execute(String task);
}/*** @Description: 命令实现,任务* @Date: 2025-01-09 8:41* @Author: gaoyufei**/
public class Task implements Command{private DutyStudent dutyStudent;@Overridepublic void setDutyStudent(DutyStudent dutyStudent) {this.dutyStudent = dutyStudent;}@Overridepublic void execute(String task) {this.dutyStudent.receiveTask(task);}
}/*** @Description: 卫生委员* @Date: 2025-01-09 8:45* @Author: gaoyufei**/
public class ClassHealthRepresentative {private Command task;public void setTask(Command task){this.task=task;}public void invoke(String task){this.task.execute(task);}
}/*** @Description: 任务板* @Date: 2025-01-09 8:46* @Author: gaoyufei**/
public class TaskBoard {public static void main(String[] args) {//卫生委员ClassHealthRepresentative classHealthRepresentative=new ClassHealthRepresentative();Command task=new Task();DutyStudent dutyStudent1 =new DutyStudent("小明");task.setDutyStudent(dutyStudent1);//小明是值日生,今日扫地classHealthRepresentative.setTask(task);classHealthRepresentative.invoke("今天扫地");DutyStudent dutyStudent2 =new DutyStudent("小花");task.setDutyStudent(dutyStudent2);//小花是值日生,今日打水classHealthRepresentative.setTask(task);classHealthRepresentative.invoke("今天打水");}
}

4、人通过遥控控制电视案例

这是一个简单的电视遥控器系统,可以实现打开、关闭和调整音量的功能。
TV 类:接受者,封装请求相关一系列的操作。
Command 接口:定义了 execute 和 undo 方法,所有具体命令都需要实现这两个方法。
TVOffCommand、TVOnCommand、TVDownVolumeCommand、TVUpVolumeCommand 类:命令具体实现,每个命令类封装了一个接收者对象,并调用接收者的相应方法。
RemoteControl 类:调用者(遥控器),它可以绑定命令对象,并在接收到请求时调用相应的命令对象的 execute 方法。
People类:客户端,通过遥控器操作TV。

java">/*** @Description: 接受者 电视* @Date: 2025-01-09 9:47* @Author: gaoyufei**/
public class TV {private boolean status = false;private Integer volume = 3;public void on() {status = true;System.out.println("电视已打开");}public void off() {status = false;System.out.println("电视已关闭");}public void valumeUp() {volume++;System.out.println("音量调到了" + volume);}public void valumeDown() {volume--;System.out.println("音量调到了" + volume);}
}/*** @Description: 命令接口* @Date: 2025-01-09 9:55* @Author: gaoyufei**/
public interface Command {void setTV(TV tv);void execute();void undo();
}/*** @Description: 关机* @Date: 2025-01-09 10:02* @Author: gaoyufei**/
public class TVOffCommand implements Command{private TV tv;@Overridepublic void setTV(TV tv) {this.tv=tv;}@Overridepublic void execute() {this.tv.off();}@Overridepublic void undo() {this.tv.on();}
}/*** @Description: 开机* @Date: 2025-01-09 9:56* @Author: gaoyufei**/
public class TVOnCommand implements Command{private TV tv;@Overridepublic void setTV(TV tv) {this.tv=tv;}@Overridepublic void execute() {tv.on();}@Overridepublic void undo() {tv.off();}
}/*** @Description: 调低音量* @Date: 2025-01-09 10:05* @Author: gaoyufei**/
public class TVDownVolumeCommand implements Command{private TV tv;@Overridepublic void setTV(TV tv) {this.tv=tv;}@Overridepublic void execute() {this.tv.valumeDown();}@Overridepublic void undo() {this.tv.valumeUp();}
}/*** @Description: 调高音量* @Date: 2025-01-09 10:05* @Author: gaoyufei**/
public class TVUpVolumeCommand implements Command{private TV tv;@Overridepublic void setTV(TV tv) {this.tv=tv;}@Overridepublic void execute() { this.tv.valumeUp(); }@Overridepublic void undo() {this.tv.valumeDown();}
}/*** @Description: 遥控* @Date: 2025-01-09 10:08* @Author: gaoyufei**/
public class RemoteControl {private Command command;public void setCommand(Command command){this.command=command;}public void invode(){command.execute();}public void undo(){command.undo();}
}/*** @Description: 人* @Date: 2025-01-09 10:11* @Author: gaoyufei**/
public class People {public static void main(String[] args) {TV tv=new TV();RemoteControl remoteControl=new RemoteControl();//开启Command on=new TVOnCommand();on.setTV(tv);remoteControl.setCommand(on);remoteControl.invode();//调大音量Command upVolume=new TVUpVolumeCommand();upVolume.setTV(tv);remoteControl.setCommand(upVolume);remoteControl.invode();remoteControl.undo();
//        //调小音量
//        Command downVolume=new TVDownVolumeCommand();
//        downVolume.setTV(tv);
//        remoteControl.setCommand(downVolume);
//        remoteControl.invode();//关闭Command off=new TVOffCommand();off.setTV(tv);remoteControl.setCommand(off);remoteControl.invode();remoteControl.undo();}
}

http://www.ppmy.cn/server/157597.html

相关文章

下载导出Tomcat上的excle文档,浏览器上显示下载

目录 1.前端2.Tomcat服务器内配置3.在Tomcat映射的文件内放置文件4.重启Tomcat,下载测试 1.前端 function downloadFile() {let pictureSourceServer "http://192.168.1.1:8080/downFile/";let fileName "测试文档.xlsx";let fileURL pictu…

DELTA并联机械手视觉方案荣获2024年度机器人应用典型案例奖

直击现场 2025年1月9日晚,2024深圳市机器人年度评选颁奖典礼在深圳市南山区圣淘沙酒店正式拉开帷幕。本次颁奖活动由中国科学院深圳先进技术研究院指导,深圳市机器人协会与《机器人与智能系统》杂志组织承办。 正运动公司受邀参与此次典礼,…

使用 Multer 上传图片到阿里云 OSS

文件上传到哪里更好? 上传到服务器本地 上传到服务器本地,这种方法在现今商业项目中,几乎已经见不到了。因为服务器带宽,磁盘 IO 都是非常有限的。将文件上传和读取放在自己服务器上,并不是明智的选择。 上传到云储存…

概要性了解Linux的总线设备驱动

引言 假如我们的板子上有很多LED,有时候需要操作这个LED,有时候需要操作另一个LED,我们希望代码可以清晰地组织在一起,方便扩展,同时自动为这些具体的设备生成对应的设备文件以供用户空间使用。 在Linux中&#xff0…

代理模式简介

代理模式是一种设计模式,它允许我们通过一个中介对象来间接访问目标对象,这个中介对象称为“代理”。代理模式的关键在于,它在不改变目标对象代码的前提下,通过引入代理对象来增加额外的功能或控制对目标对象的访问。 代理模式的基…

npm run 运行项目报错:Cannot resolve the ‘pnmp‘ package manager

尝试使用 npm 运行一个项目,但是在解析 pnmp 包管理器时遇到了问题。这通常意味着项目可能配置错误,或者可能误输入了命令。 解决方法: 确认是否有拼写错误。通常情况下,应该是 npm 而不是 pnmp。 检查项目的 package.json 文件&…

弹性云服务器和普通服务器的区别

云服务器随着云计算的快速发展,也受到了各个企业的广泛使用,随着业务需求的不断变化,云服务器的类型也在不断进行细化,其中弹性云服务器逐渐受到企业的欢迎,那么弹性云服务器和普通服务器究竟有什么区别呢?…

Linux内核 -- RTC 驱动的注册方式

Linux 内核中 RTC 驱动的注册方式 在 Linux 内核中,RTC(Real-Time Clock)驱动的注册可以通过多种方式实现,以下整理了常见的注册方式及其注意事项。 1. 使用 devm_rtc_device_register 这是注册 RTC 驱动的最常用方法&#xff…