设计模式(行为型设计模式——命令模式)

设计模式(行为型设计模式------命令模式)

命令模式

基本定义

将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。

模式结构

  • Command:抽象命令类
  • ConcreteCommand:具体命令类
  • Invoker:调用者,命令的传递者
  • Receiver:接收者,执行命令功能的相关操作,是具体命令对象业务的真正实现者。
  • Client:客户类

代码实现

Command
java 复制代码
public abstract class Command {
 //需要加载接收者类,将receiver加载
    final static Receiver receiver = new Receiver();
    int memoryValue;

    public abstract int execute(int value);

    //撤销操作
    public abstract int reset();

}
ConcreteCommand 具体命令类
java 复制代码
public class AddCommand extends Command {

    @Override
    public int execute(int value) {
        super.memoryValue = value;
        return super.receiver.add(value);
    }

    @Override
    public int reset() {
        return super.receiver.subtract(memoryValue);
    }
}
java 复制代码
public class MultiCommand extends Command{

    @Override
    public int execute(int value) {
        super.memoryValue = value;
        return this.receiver.multi(value);
    }

    @Override
    public int reset() {
        return receiver.division(super.memoryValue);
    }
}
Invoker 调用者
java 复制代码
@Slf4j
public class Invoker {
    //调用者发送命令, 所以需要将命令类关联进来
    Command command;

    public Invoker(Command command) {
        this.command = command;
    }

    public void setCommand(Command command) {
        this.command = command;
    }

    public void calc(int value){
        int result = command.execute(value);
        log.info("计算操作:执行结果:{} ", result);
    }

    public void cancel(){
        int result = command.reset();
        log.info("撤销操作,执行结果:{}", result);
    }
}
Receiver 接收者
java 复制代码
@Slf4j
public class Receiver {

    private int number;

    public int add(int value){
        log.info("加法 {} + {} ", number, value);
        return number += value;
    }

    public int subtract(int value){
        log.info("减法 {} - {} ", number, value);
        return number -= value;
    }

    public int multi(int value){
        log.info("乘法 {} * {} ", number, value);
        return number *= value;
    }

    public int division(int value){
        log.info("除法 {} / {} ", number, value);
        return number /= value;
    }
}
测试类
java 复制代码
public class Test {

    public static void main(String[] args){
        Command add = new AddCommand();
        Invoker invoker = new Invoker(add);
        invoker.calc(10);
        invoker.calc(20);
        invoker.cancel();

        Command multi = new MultiCommand();
        invoker.setCommand(multi);
        invoker.calc(3);
        invoker.calc(2);
        invoker.cancel();
    }
}
输出结果

CalcReceiver - 加法 0 + 10

CalcInvoker - 计算操作:执行结果:10

CalcReceiver - 加法 10 + 20

CalcInvoker - 计算操作:执行结果:30

CalcReceiver - 减法 30 - 20

CalcInvoker - 撤销操作,执行结果:10

CalcReceiver - 乘法 10 * 3

CalcInvoker - 计算操作:执行结果:30

CalcReceiver - 乘法 30 * 2

CalcInvoker - 计算操作:执行结果:60

CalcReceiver - 除法 60 / 2

CalcInvoker - 撤销操作,执行结果:30

枚举实现

java 复制代码
//抽象命令类
public enum CalcEnum {
    //ConcreteCommand具体命令类
    ADD("加法"){
        @Override
        public int execute(int value) {
            super.memoryValue = value;
            return super.receiver.add(value);
        }

        @Override
        public int reset() {
            //减去记忆数值
            return super.receiver.subtract(super.memoryValue);
        }
    },
    //ConcreteCommand具体命令类
    MULTI("乘法"){
        @Override
        public int execute(int value) {
            super.memoryValue = value;
            return super.receiver.multi(value);
        }

        @Override
        public int reset() {
            return super.receiver.division(super.memoryValue);
        }
    };

    CalcEnum(String name) {
        this.name = name;
    }

    private String name;

    public abstract int execute(int value);
    public abstract int reset();
    int memoryValue;
    final static Receiver receiver = new Receiver();
}
调用者
java 复制代码
@Slf4j
public class CalcInvoker {
    private CalcEnum calcEnum;

    public CalcInvoker(CalcEnum calcEnum) {
        this.calcEnum = calcEnum;
    }

    public void setCalcEnum(CalcEnum calcEnum) {
        this.calcEnum = calcEnum;
    }
    public void calc(int value){
        int result = calcEnum.execute(value);
        log.info("计算操作:执行结果:{} ", result);
    }

    public void cancel(){
        int result = calcEnum.reset();
        log.info("撤销操作,执行结果:{}", result);
    }
}
测试类
java 复制代码
public class CalcTest {

    public static void main(String[] args) {

        CalcInvoker invoker = new CalcInvoker(CalcEnum.ADD);
        invoker.calc(10);
        invoker.calc(20);
        invoker.cancel();

        invoker.setCalcEnum(CalcEnum.MULTI);
        invoker.calc(3);
        invoker.calc(2);
        invoker.cancel();

    }
}
输出结果

加法 0 + 10

计算操作:执行结果:10

加法 10 + 20

计算操作:执行结果:30

减法 30 - 20

撤销操作,执行结果:10

乘法 10 * 3

计算操作:执行结果:30

乘法 30 * 2

计算操作:执行结果:60

除法 60 / 2

撤销操作,执行结果:30

优点

  • 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。

  • 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足"开闭原则",对扩展比较灵活。

  • 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。

  • 方便实现 Undo 和 Redo 操作。命令模式可以备忘录模式结合,实现命令的撤销与恢复。

缺点

可能产生大量具体命令类。因为针对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。

应用场景

  • 当系统需要将请求调用者与请求接收者解耦时,命令模式使得调用者和接收者不直接交互。

  • 当系统需要随机请求命令或经常增加或删除命令时,命令模式比较方便实现这些功能。

  • 当系统需要执行一组操作时,命令模式可以定义宏命令来实现该功能。

  • 当系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作时,可以将命令对象存储起来,采用备忘录模式来实现。

相关推荐
程序猿阿伟2 分钟前
《深度探秘:Java构建Spark MLlib与TensorFlow Serving混合推理流水线》
java·spark-ml·tensorflow
TDengine (老段)11 分钟前
TDengine 开发指南—— UDF函数
java·大数据·数据库·物联网·数据分析·tdengine·涛思数据
键盘林14 分钟前
分布式系统简述
java·开发语言
可儿·四系桜15 分钟前
如何在 Java 中优雅地使用 Redisson 实现分布式锁
java·开发语言·分布式
昕冉26 分钟前
利用Axure 9中继器绘制数据统计表原型图
设计模式·设计
sszdzq30 分钟前
SpringCloudGateway 自定义局部过滤器
java·spring boot
消失的旧时光-194337 分钟前
Android 开发中配置 USB 配件模式(Accessory Mode) 配件过滤器的配置
android·java
IDRSolutions_CN43 分钟前
如何在网页里填写 PDF 表格?
java·经验分享·pdf·软件工程·团队开发
-兰天白云-1 小时前
java转pdf工具对比
java
BillKu1 小时前
Java中List的forEach用法详解
java·windows·list