设计模式轻松学【十二】命令模式

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 作为一名小白开发,你的领导命令你去做一件事情,这就是命令。而这里面包括了命令的发送者(领导),命令的执行者(你)及命令本身,并且他还可以发出一连串的命令,你得一个个去做。

在程序中,我们每敲一行命令都会得到回复,比如SQL命令。

这样的例子非常多,例如,电视机遥控器(命令发送者)通过按钮(具体命令)来遥控电视机(命令接收者)。

定义与特点

  • 定义

    将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。命令模式通过这种封装的方式实现将客户端和接收端解耦。

  • 详细概述

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

    命令模式也支持可撤销的操作。命令模式通过这种封装的方式实现将客户端和接收端解耦。命令模式属于行为型模式。

  • 参与角色

    • 抽象命令接口(Command):定义命令的接口,拥有执行命令的抽象方法 execute()。
    • 具体的命令对象(ConcreteCommand):抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
    • 接收者对象(Receiver):命令接收者,命令的实际执行者。
    • 命令发送者(Invoker):请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
  • 结构类图

    image.png

模式实现分析

由于物联网快速发展,BAT纷纷布局智能家居市场,假设现在你买了台百度制造的小度音箱,他可以控制你家的电视....

现在我们使用命令模式来实现该程序

  • 创建抽象命令接口

    //抽象的命令接口
    interface Command {
        //执行命名的接口
        void execute();
    }
  • 命令接受者

    //电视
    class TV {
        public void tvOn() {
            System.out.println("电视打开了!!");
        }
    
        public void tvOff() {
            System.out.println("电视关上了!!");
        }
    }
  • 具体的命令接口(开、关电视)

    //开电视命令
    class TvOnCommand implements Command{
    
        private TV tv;
    
        public TvOnCommand(TV tv) {
            this.tv = tv;
        }
    
        @Override
        public void execute() {
            tv.tvOn();
        }
    }
    
    //关电视命令
    class TvOffCommand implements Command{
    
        private TV tv;
    
        public TvOffCommand(TV tv) {
            this.tv = tv;
        }
    
        @Override
        public void execute() {
            tv.tvOff();
        }
    }
  • 传递命令对象

    class XiaoDu {
    
        private Command command;
        
        //设置具体的命令,依赖注入
        public void setCommand(Command command) {
            this.command = command;
        }
        //执行命令
        public void doCommand() {
            command.execute();
        }
    }
  • 调用客户端

    public class CommandClient {
    
        public static void main(String[] args) {
            // 创建小度同学
            XiaoDu xiaoDu = new XiaoDu();
            // 创建具体的等对象,相当于具体的命令接受者
            TV tv = new TV();
            
            // 创建了开电视的命令,你就是命令的发起者
            System.out.println("小度同学帮我把电视开一下!");
            
            TvOnCommand tvOnCommand = new TvOnCommand(tv);
            // 小度同学接受到了你发出的命令,并执行命令
            xiaoDu.setCommand(tvOnCommand);
            xiaoDu.doCommand();
        }
    }
    //运行结果
    小度同学帮我把电视开一下!
    电视打开了!!

上面的例子仅仅是实现单个命令的的命令模式,而命令模式是可以相当复杂的,就比如说,你让小度同学帮你打电视机,并且打开灯,并且帮你打开窗帘,并且打开空调等等,这时候我们可以将多个命令存储起来,然后一次性执行。

通过上面的案例,我们知道命令模式就是把命令封装成对象,然后将动作请求者与动作执行者完全解耦,比如遥控器的按钮和电器没有任何关系。也就是说命令的发送者和命令执行者有不同的生命周期。命令发送了并不是立即执行。

总结

优点

  • 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
  • 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
  • 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
  • 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。

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

宏命令

将多个命令存储起来,发出执行宏命令请求的之后执行存储的所有命令。

命令撤销

在我们发出某个请求并执行之后,将命令的执行状态进行保存,如果我们想要回归执行这个命令之前的状态,我们就可以通过命令撤销的方式回归到之前的状态。

队列

还记得定义中提到了队列,命令模式如何用于队列呢,比如饭店有很多个点菜的地方,有一个做菜的地方,把点菜看作命令,做菜看作命令执行者,不断有人点菜就相当于把菜加入队列,对于做菜的只管从队列里面取,取一个做一个。

日志

定义中还提到了日志,日志一般用于记录用户行为,或者在异常时恢复时用的,比如每个命令现在包含两个方法,一个执行execute,一个undo(上例中为了方便大家理解,没有写undo),我们可以把用户所有命令调用保存到日志中,比如用户操作不当了,电器异常了,我们只需要把日志中所有的命令拿出来执行一遍undo就完全恢复了。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
3月前
|
设计模式 UED
二十三种设计模式:解锁软件开发的神器:命令模式与撤销重做功能
二十三种设计模式:解锁软件开发的神器:命令模式与撤销重做功能
|
1天前
|
设计模式 存储 Java
【十二】设计模式~~~行为型模式~~~命令模式(Java)
文章详细介绍了命令模式(Command Pattern),这是一种对象行为型模式,用于将请求封装成对象,实现请求发送者与接收者的解耦,从而降低系统耦合度、提高灵活性,并支持命令的排队、记录、撤销和恢复操作。通过案例分析、结构图、时序图和代码示例,文章展示了命令模式的组成部分、实现方式和应用场景,并讨论了其优点、缺点和适用情况。
|
1月前
|
设计模式 JavaScript API
js设计模式【详解】—— 命令模式
js设计模式【详解】—— 命令模式
29 6
|
2月前
|
设计模式
命令模式-大话设计模式
命令模式-大话设计模式
15 2
|
2月前
|
设计模式 Java uml
必知的技术知识:JAVA【设计模式】命令模式
必知的技术知识:JAVA【设计模式】命令模式
16 0
|
2月前
|
设计模式 Java
Java设计模式之命令模式详解
Java设计模式之命令模式详解
|
2月前
|
设计模式
设计模式之命令模式
设计模式之命令模式
|
3月前
|
设计模式 Java 调度
【设计模式系列笔记】命令模式
命令模式是一种行为设计模式,它将请求封装成一个对象,从而允许使用不同的请求、队列或日志请求参数化客户端对象,同时支持撤销操作。
48 1
|
3月前
|
设计模式 存储 Java
【搞懂设计模式】命令模式:从遥控器到编程的妙用!
【搞懂设计模式】命令模式:从遥控器到编程的妙用!
42 0
|
3月前
|
设计模式 Java 调度
小谈设计模式(24)—命令模式
小谈设计模式(24)—命令模式