• 详解设计模式:命令模式


    命令模式(Command Pattern)也被称为行动模式(Action Pattern)、事物模式(Transaction Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。

    命令模式 是一种数据驱动的设计模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。命令是对命令的封装,每一个命令都是一个操作,请求方发出请求,接收方接收请求,并执行操作。命令模式解耦了请求方和接收方。

    本篇文章内容包括:关于命令模式、命令模式 Demo



    一、关于命令模式

    1、关于命令模式

    命令模式(Command Pattern)也被称为行动模式(Action Pattern)、事物模式(Transaction Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。

    命令模式 是一种数据驱动的设计模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。命令是对命令的封装,每一个命令都是一个操作,请求方发出请求,接收方接收请求,并执行操作。命令模式解耦了请求方和接收方。

    2、关于命令模式的构成

    命令模式主要包含以下 4 种角色:

    • 命令(Command)角色:定义命令的接口,声明执行的方法。
    • 具体命令(Concrete Command)角色:实现命令接口,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
    • 接收者(Receiver)角色:负责具体实施和执行一个请求。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
    • 请求者(调用者)角色(Invoker):负责调用命令对象执行请求。
    3、关于命令模式的XML

    image-20221203225114649

    4、关于命令模式的使用场景

    命令模式通常适用于以下场景。

    • 请求调用者需要与请求接收者解耦时,命令模式可以使调用者和接收者不直接交互。
    • 系统随机请求命令或经常增加、删除命令时,命令模式可以方便地实现这些功能。
    • 当系统需要执行一组操作时,命令模式可以定义宏命令来实现该功能。
    • 当系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作时,可以将命令对象存储起来,采用备忘录模式来实现
    5、关于命令模式的优缺点

    # 关于命令模式优点

    • 通过引入中间件(抽象接口)降低系统的耦合度。
    • 扩展性良好,增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,且满足“开闭原则”。
    • 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
    • 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。
    • 可以在现有命令的基础上,增加额外功能。比如日志记录,结合装饰器模式会更加灵活。

    # 关于命令模式缺点

    • 使用命令模式可能会导致某些系统有过多的具体命令类。
    • 系统结构更加复杂。

    二、命令模式 Demo

    1、Demo 设计

    我们使用遥控操作电视,电视操作包括,打开、关闭以及换台

    2、Demo 实现

    # Command 命令(Command)角色

    public interface Command {
        
        /**
         * 操作命令
         */
        void execute();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    # ConcreteCommand 具体命令(Concrete Command)角色

    public class OpenCommand implements Command{
    
        private final TV tv = new TV();
    
        /**
         * 打开电视机
         */
        @Override
        public void execute() {
            tv.open();
        }
    }
    public class ChangeCommand implements Command{
    
        private final TV tv = new TV();
    
        /**
         * 换台
         */
        @Override
        public void execute() {
            tv.change();
        }
    }
    public class CloseCommand implements Command{
    
        private final TV tv = new TV();
    
        /**
         * 关闭电视机
         */
        @Override
        public void execute() {
            tv.close();
        }
    }
    
    • 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

    # Control 请求者(调用者)角色(Invoker)

    import java.util.ArrayList;
    import java.util.List;
    
    public class Control {
    
        public List<Command> commands = new ArrayList<>();
    
        public Control(Command command) {
            commands.add(command);
        }
    
        public Control(List<Command> commands) {
            this.commands.addAll(commands);
        }
    
        public void action() {
            commands.forEach(Command::execute);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    # TV 接收者(Receiver)角色

    public class TV {
    
        public void open() {
            System.out.println("打开电视机");
        }
    
        public void change() {
            System.out.println("切换电视机");
        }
    
        public void close() {
            System.out.println("关闭电视机");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    3、Demo 测试
    import java.util.ArrayList;
    import java.util.List;
    
    public class Client {
        
        public static void main(String[] args) {
            Command command = new OpenCommand();
            Command changeCommand = new ChangeCommand();
            Command closeCommand = new CloseCommand();
            List<Command> list = new ArrayList<>();
            list.add(command);
            list.add(changeCommand);
            list.add(closeCommand);
            Control control = new Control(list);
            control.action();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    Win11自动更新怎么永久关闭?
    【C语言|关键字】C语言32个关键字详解
    【Java基础】泛型+反射+枚举+Lambda表达式 知识点总结
    C++之分水岭——类和对象【上】
    考研思想政治理论大纲
    我服了,SpringBoot升级后这服务我一个星期都没跑起来(上)
    华为云云耀云服务器L实例评测|Docker版的Minio安装 & Springboot项目中的使用 & 结合vue进行图片的存取
    如何连接本地树莓派
    分析大疆官网根据ip自动跳转到指定域名
    《自然语言处理实战:利用Python理解、分析和生成文本》读书笔记:第1章 NLP概述
  • 原文地址:https://blog.csdn.net/weixin_45187434/article/details/128176316