命令模式(Command Pattern)也被称为行动模式(Action Pattern)、事物模式(Transaction Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。
命令模式 是一种数据驱动的设计模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。命令是对命令的封装,每一个命令都是一个操作,请求方发出请求,接收方接收请求,并执行操作。命令模式解耦了请求方和接收方。
~
本篇文章内容包括:关于命令模式、命令模式 Demo
文章目录
- 一、关于命令模式
 - 1、关于命令模式
 - 2、关于命令模式的构成
 - 3、关于命令模式的XML
 - 4、关于命令模式的使用场景
 - 5、关于命令模式的优缺点
 
- 二、命令模式 Demo
 - 1、Demo 设计
 - 2、Demo 实现
 - 3、Demo 测试
 
一、关于命令模式
1、关于命令模式
命令模式(Command Pattern)也被称为行动模式(Action Pattern)、事物模式(Transaction Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。
命令模式 是一种数据驱动的设计模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。命令是对命令的封装,每一个命令都是一个操作,请求方发出请求,接收方接收请求,并执行操作。命令模式解耦了请求方和接收方。
2、关于命令模式的构成
命令模式主要包含以下 4 种角色:
- 命令(Command)角色:定义命令的接口,声明执行的方法。
 - 具体命令(Concrete Command)角色:实现命令接口,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
 - 接收者(Receiver)角色:负责具体实施和执行一个请求。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
 - 请求者(调用者)角色(Invoker):负责调用命令对象执行请求。
 
3、关于命令模式的XML

4、关于命令模式的使用场景
命令模式通常适用于以下场景。
- 请求调用者需要与请求接收者解耦时,命令模式可以使调用者和接收者不直接交互。
 - 系统随机请求命令或经常增加、删除命令时,命令模式可以方便地实现这些功能。
 - 当系统需要执行一组操作时,命令模式可以定义宏命令来实现该功能。
 - 当系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作时,可以将命令对象存储起来,采用备忘录模式来实现
 
5、关于命令模式的优缺点
# 关于命令模式优点
- 通过引入中间件(抽象接口)降低系统的耦合度。
 - 扩展性良好,增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,且满足“开闭原则”。
 - 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
 - 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。
 - 可以在现有命令的基础上,增加额外功能。比如日志记录,结合装饰器模式会更加灵活。
 
# 关于命令模式缺点
- 使用命令模式可能会导致某些系统有过多的具体命令类。
 - 系统结构更加复杂。
 
二、命令模式 Demo
1、Demo 设计
我们使用遥控操作电视,电视操作包括,打开、关闭以及换台
2、Demo 实现
# Command 命令(Command)角色
public interface Command {
    
    /**
     * 操作命令
     */
    void execute();
}
 
# 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();
    }
}
 
# 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);
    }
}
 
# TV 接收者(Receiver)角色
public class TV {
    public void open() {
        System.out.println("打开电视机");
    }
    public void change() {
        System.out.println("切换电视机");
    }
    public void close() {
        System.out.println("关闭电视机");
    }
}
 
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();
    }
}
                ![序列类型(元组()、列表[]、字符串““)、集合类型({}、set())](https://img-blog.csdnimg.cn/bbdb679ff3e64ea1a42cdf602ea53c97.png)










![[附源码]Python计算机毕业设计SSM竞赛报名管理系统(程序+LW)](https://img-blog.csdnimg.cn/64ae3c31059040209ee0e959d902f434.png)







