Java设计模式—命令模式(Command Pattern)

命令模式

业务需求

  • 智能生活项目需求
  • 有一套只能家电,有照明灯,风扇,冰箱,洗衣机,我们只需要手机安装app即可控制这些家电
  • 这些智能家电来自不同的厂家,不想每个家电都安装app分别控制,希望只安装一个app就可以控制全部智能家电
  • 要实现一个app控制所有只能家电的需要,需要每个只能家电提供一个统一的接口调用,适合使用命令模式
  • 命令模式可以将动作的请求者,从动作的执行者对象汇总解耦出来
  • 本例中,动作请求者是手机app,都做执行者是每个厂商的一个家电产品

基本介绍

  • 命令模式,在设计软件中,我们经常需要向某些对象发送请求,但是不知道具体请求接收是谁,也不知道被请求操作的是哪个;只需在程序运行时指定具体的接受者即可,使用命令模式设计
  • 命令模式使请求发送者与请求接受者消除彼此耦合,让对象之间调用关系更加灵活
  • 在命令模式中,会将一个请求封装为一个对象,便于使用不同参数来表示不同请求,命令模式也支持撤销操作
  • 通俗理解,长官发出命令,士兵去执行;长官是调用者Invoke,士兵是接受者Receiver,MyCommond是命令,实现了Commond接口,持有接收对象

原理类图
Java设计模式—命令模式(Command Pattern)_第1张图片
原理类图说明

  • Invoker:调用者角色
  • Command:命令角色,包含需要执行的所有命令,可以是接口或抽象类
  • Receiver:接收者角色,知道如何实施和执行一个请求相关操作
  • ConcreteCommand:将一个接收者对象和一个动作绑定,调用接收者相应的操作,实现excute

代码实现
Java设计模式—命令模式(Command Pattern)_第2张图片
定义接收者,具体执行功能

public class LightReceiver {
    public void on() {
        System.out.println("电灯打开了...");
    }
    public void off() {
        System.out.println("电灯关闭了...");
    }
}

命令接口

/ 命令接口
public interface Command {
    // 执行动作
    public void excute();
    // 撤销动作
    public void undo();
}

开命令

public class LightOnCommand implements Command {
    //聚合LightReceiver
    LightReceiver light;
    // 构造
    public LightOnCommand(LightReceiver light) {
        this.light = light;
    }
    @Override
    public void excute() {
        light.on();
    }
    @Override
    public void undo() {
        light.off();
    }
}

关命令

public class LightOffCommand implements Command {
    //聚合LightReceiver
    LightReceiver light;
    // 构造
    public LightOffCommand(LightReceiver light) {
        this.light = light;
    }
    @Override
    public void excute() {
        light.off();
    }
    @Override
    public void undo() {
        light.on();
    }
}

空命令

// 空执行,用于初始化
public class NoCommand implements Command{
    @Override
    public void excute() {
        // 空操作
    }
    @Override
    public void undo() {
        // 空操作
    }
}

遥控器,整合接收者和命令

public class RemoteController {
    //开 按钮命令组
    Command[] onCommands;
    Command[] offCommands;
    // 记住最近的一次操作,用于撤销
    Command undoCommand;
    // 构造器,完成按钮初始化
    public RemoteController() {
        onCommands = new Command[5];
        offCommands = new Command[5];
        // 用空操作初始化
        for (int i=0; i<5;i++) {
            onCommands[i] = new NoCommand();
            offCommands[i] = new NoCommand();
        }
    }
    // 设置需要的命令
    public void setCommand(int no, Command onCommand, Command offCommand) {
        onCommands[no] = onCommand;
        offCommands[no] = offCommand;
    }
    // 按下开按钮
    public void onButtonWasPushed(int no) {
        // 找到对应按钮,调用对应方法
        onCommands[no].excute();
        // 记录这次操作,用于撤销
        undoCommand = onCommands[no];
    }
    // 按下关按钮
    public void offButtonWashPushed(int no) {
        offCommands[no].excute();
        undoCommand = offCommands[no];
    }
    // 按下撤销按钮
    public void undoButtonWasPushed() {
        undoCommand.undo();
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        // 接收者
        LightReceiver lightReceiver = new LightReceiver();
        // 开关命令
        LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
        LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);
        // 遥控器
        RemoteController remoteController = new RemoteController();
        // 设置命令
        remoteController.setCommand(0, lightOnCommand, lightOffCommand);

        System.out.println("按下开灯按钮===============");
        remoteController.onButtonWasPushed(0);
        System.out.println("按下关灯按钮===============");
        remoteController.onButtonWasPushed(0);
        System.out.println("撤销=====================");
        remoteController.undoButtonWasPushed();
    }
}

Java设计模式—命令模式(Command Pattern)_第3张图片
说明

  • 如果扩展新的功能,需要新增新的接收者、开命令、关命令;
  • 空命令可以保存最近的一次命令,方便随时撤销最近的命令,也就是执行最近命令的相反命令
  • 结构略复杂,实质就是命令类聚合了接收者,遥控器聚合了命令类

Spring源码分析—JdbcTemplate

命令模式注意事项

  • 将发请求的对象和执行请求的对象解耦;命令对象负责纽带桥梁作用,请求发起者和请求执行者之间的解耦通过命令对象实现
  • 容易设计一个命令队列,把命令放到队列中,可以多线程执行命令
  • 容易实现对请求的撤销和重做
  • 命令模式不足,造成系统有过多的类,增加系统复杂度
  • 空命令也是一种设计模式,为我们省去了判断空的操作;如果没有空命令,可能每按下按键都要判断空,造成编码麻烦
  • 命令模式经典应用场景,界面的一个个按钮命令,模拟CMD订单的撤销/回复,触发-反馈机制

你可能感兴趣的:(Java设计模式,java,设计模式)