Java实现命令模式

一、简介

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();
    }
}
相关推荐
一决威严-雪雪2 小时前
springboot整合admin
java·spring boot·后端
栗筝i2 小时前
Spring 中的常用注解
java·后端·spring
小登ai学习2 小时前
框架部分面试题学习
java·学习·面试
写代码的熊萌新3 小时前
JAVA2-类与对象编程(1)
java·开发语言
知初~3 小时前
SpringBoot3
java·spring boot·spring·log4j·maven
kkkkatoq3 小时前
EasyExcel的应用
java·前端·servlet
牛马程序员‍4 小时前
Day97 minio
java·对象存储·minio·oss
!!!5254 小时前
lombok在高版本idea中注解不生效的解决
java·服务器·前端
F-2H4 小时前
C语言:构造类型(共用体/联合体,枚举)
java·linux·c语言·开发语言·数据结构·c++·算法