一、简介
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;
}
@Override
public 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;
@Override
public void setEmployee(Employee employee) {
this.employee=employee;
}
@Override
public 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;
@Override
public void setDutyStudent(DutyStudent dutyStudent) {
this.dutyStudent = dutyStudent;
}
@Override
public 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;
@Override
public void setTV(TV tv) {
this.tv=tv;
}
@Override
public void execute() {
this.tv.off();
}
@Override
public void undo() {
this.tv.on();
}
}
/**
* @Description: 开机
* @Date: 2025-01-09 9:56
* @Author: gaoyufei
**/
public class TVOnCommand implements Command{
private TV tv;
@Override
public void setTV(TV tv) {
this.tv=tv;
}
@Override
public void execute() {
tv.on();
}
@Override
public void undo() {
tv.off();
}
}
/**
* @Description: 调低音量
* @Date: 2025-01-09 10:05
* @Author: gaoyufei
**/
public class TVDownVolumeCommand implements Command{
private TV tv;
@Override
public void setTV(TV tv) {
this.tv=tv;
}
@Override
public void execute() {
this.tv.valumeDown();
}
@Override
public void undo() {
this.tv.valumeUp();
}
}
/**
* @Description: 调高音量
* @Date: 2025-01-09 10:05
* @Author: gaoyufei
**/
public class TVUpVolumeCommand implements Command{
private TV tv;
@Override
public void setTV(TV tv) {
this.tv=tv;
}
@Override
public void execute() { this.tv.valumeUp(); }
@Override
public 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();
}
}