• 软件设计模式系列之十六——命令模式


    1 模式的定义

    命令模式(Command Pattern)是一种行为型设计模式,旨在将请求发送者和接收者解耦,将一个请求封装为一个对象,从而允许您参数化客户端对象以进行不同的请求、排队请求或记录请求,并支持可撤销操作。

    命令模式的核心思想是将一个请求包装成一个对象,包括请求的参数和接收者对象,然后客户端只需要调用该对象的方法来执行请求,而不需要关心请求的具体细节。这种方式使得请求的发送者和接收者之间的关系变得松耦合,同时支持一些附加功能,如命令的撤销和重做。

    2 举例说明

    为了更好地理解命令模式,让我们考虑一个实际的例子:遥控器控制家电。假设您有一个遥控器,可以控制不同种类的家电设备,如电视、音响和灯。每个按钮都代表一个命令,例如打开电视、关闭音响、调暗灯光等。命令模式可以用于实现这种遥控器系统。
    在这里插入图片描述

    在这个例子中,每个命令(如打开电视)都被封装成一个命令对象,包括具体的操作(执行命令)和接收者对象(执行命令的设备)。遥控器上的按钮只需要关联一个命令对象,并在按下按钮时执行该命令。这种方式使得遥控器可以轻松控制不同种类的家电设备,而不需要关心它们的具体实现。

    3 结构

    命令模式的结构包括以下几个关键部分:
    在这里插入图片描述

    Command(命令):定义一个执行操作的接口,通常包括一个 execute 方法,负责执行具体的命令。

    ConcreteCommand(具体命令):实现命令接口,将一个接收者对象绑定到一个操作。它负责调用接收者的方法来执行命令。

    Receiver(接收者):负责执行与请求相关的具体操作,是命令真正的执行者。

    Invoker(调用者):负责将命令对象传递给接收者执行命令,它不需要知道命令的具体细节,只需调用命令的 execute 方法即可。

    Client(客户端):创建具体命令对象,并将命令对象与接收者对象关联,然后将命令对象传递给调用者来执行。

    4 实现步骤

    实现命令模式时,通常遵循以下步骤:

    定义命令接口(Command),其中包括一个 execute 方法用于执行命令。

    创建具体命令类(ConcreteCommand),实现命令接口,并在构造函数中绑定一个接收者对象。

    定义接收者类(Receiver),负责执行具体的操作。

    创建调用者类(Invoker),负责接收命令对象并执行命令。

    在客户端中创建命令对象和接收者对象,并将它们关联。然后将命令对象传递给调用者,由调用者执行命令。

    5 代码实现

    现在,让我们通过 Java 代码来实现上述遥控器控制家电的命令模式。

    // 1. 定义命令接口
    interface Command {
        void execute();
    }
    
    // 2. 创建具体命令类
    class LightOnCommand implements Command {
        private Light light;
    
        public LightOnCommand(Light light) {
            this.light = light;
        }
    
        @Override
        public void execute() {
            light.turnOn();
        }
    }
    
    class LightOffCommand implements Command {
        private Light light;
    
        public LightOffCommand(Light light) {
            this.light = light;
        }
    
        @Override
        public void execute() {
            light.turnOff();
        }
    }
    
    // 3. 定义接收者类
    class Light {
        public void turnOn() {
            System.out.println("Light is on");
        }
    
        public void turnOff() {
            System.out.println("Light is off");
        }
    }
    
    // 4. 创建调用者类
    class RemoteControl {
        private Command command;
    
        public void setCommand(Command command) {
            this.command = command;
        }
    
        public void pressButton() {
            command.execute();
        }
    }
    
    // 5. 客户端代码
    public class Client {
        public static void main(String[] args) {
            // 创建接收者对象
            Light light = new Light();
    
            // 创建具体命令对象并关联接收者
            Command lightOn = new LightOnCommand(light);
            Command lightOff = new LightOffCommand(light);
    
            // 创建调用者
            RemoteControl remote = new RemoteControl();
    
            // 设置命令并执行
            remote.setCommand(lightOn);
            remote.pressButton();
    
            remote.setCommand(lightOff);
            remote.pressButton();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    6 典型应用场景

    命令模式在实际应用中有多种典型场景,包括但不限于:

    遥控器控制:如上面的示例所示,可以用命令模式实现遥控器来控制不同的家电设备,如电视、音响和灯。

    文本编辑器操作:文本编辑器中的撤销、重做、剪切、复制、粘贴等操作可以使用命令模式来实现。

    菜单系统:图形用户界面(GUI)应用中的菜单项和按钮操作可以通过命令模式来处理。
    在这里插入图片描述

    游戏中的动作:在游戏中,角色的动作和命令(如攻击、防御、跳跃等)可以使用命令模式来处理。

    多级撤销操作:命令模式支持撤销和重做操作,因此在需要多级撤销的应用中很有用,如图像编辑器或CAD软件。

    日程安排应用:在日程安排应用中,可以使用命令模式来处理添加、编辑、删除事件等操作。

    7 优缺点

    优点:

    解耦发送者和接收者:命令模式将请求的发送者和接收者解耦,发送者不需要知道接收者的具体实现,从而降低了系统的耦合度。

    支持撤销和重做:命令模式可以轻松支持命令的撤销和重做,因为每个命令对象都包含了执行和撤销操作的逻辑。

    支持扩展:可以轻松添加新的命令和接收者,而无需修改现有的客户端代码。

    支持排队请求:命令模式允许将请求排队,以便按照先后顺序执行,或者实现任务调度。

    缺点:

    可能导致命令类膨胀:如果有大量的命令操作,可能会导致命令类的膨胀,增加维护的复杂性。

    不适用于所有情况:命令模式不适用于所有场景,特别是对于简单的命令,直接调用方法可能更加简单和高效。

    增加代码复杂性:引入命令模式会增加一定的代码复杂性,因为需要创建额外的命令类和接收者类。

    8 类似模式

    策略模式(Strategy Pattern):策略模式也可以用于封装可互换的行为,但它的主要目的是在运行时选择算法或策略,而不是将请求封装成命令对象。

    观察者模式(Observer Pattern):观察者模式用于定义对象之间的一对多依赖关系,当一个对象状态发生变化时,所有依赖于它的对象都会收到通知。与命令模式不同,观察者模式不涉及命令的封装和执行。

    中介者模式(Mediator Pattern):中介者模式用于减少对象之间的直接耦合,将对象之间的通信集中在一个中介者对象中。与命令模式不同,中介者模式通常用于管理对象之间的交互,而不是将请求封装成命令。

    9 小结

    命令模式是一种有用的设计模式,它允许将请求封装成命令对象,从而解耦请求的发送者和接收者,支持撤销和重做操作,并提供扩展性和灵活性。命令模式在实际应用中有多种典型场景,包括遥控器控制、文本编辑器操作、菜单系统等。虽然命令模式增加了一些复杂性,但它可以提高代码的可维护性和可扩展性,是面向对象设计中的重要模式之一。

  • 相关阅读:
    阿里云对象存储OSS文件无法预览,Bucket设置了Referer
    想进大厂的朋友请注意!Java多线程面试题来袭,跳槽涨薪必备法器
    怎么做口碑营销?口碑营销有哪些方式?
    LeetCode 1161.最大层内元素和:层序遍历
    认识 https 以及 https的通信流程
    前端&UI核心
    面试总结 - 计算机网络
    JAVA 集合框架(二) List集合详解和常用方法
    基于JAVA学校运动会信息管理系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署
    docker提交镜像到阿里ack整体流程
  • 原文地址:https://blog.csdn.net/cooldream2009/article/details/133295298