行为型 中等
命令模式
Command Pattern
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
概述
命令模式是一种行为设计模式,它可将请求转换为一个包含与请求相关的所有信息的独立对象。此转换让你能根据不同的请求将方法参数化、延迟请求执行或将其放入队列中,且能实现可撤销操作。
适用场景
- •当需要通过操作来参数化对象时
- •当需要将操作放入队列中、延迟执行或远程执行时
- •当需要实现操作回滚功能时
- •当需要实现宏命令(组合多个命令)时
- •当需要记录操作历史以便撤销/重做时
优点
- +单一职责原则:将触发操作的对象与执行操作的对象解耦
- +开闭原则:可以在不更改现有代码的情况下引入新命令
- +可以实现撤销和重做
- +可以实现操作的延迟执行
- +可以将多个命令组合成宏命令
缺点
- −代码可能会变得更加复杂,因为需要引入许多新的类
- −每个具体命令都需要创建一个类,可能导致类数量膨胀
结构
classDiagram
class Command {
<<interface>>
+execute()
+undo()
}
class ConcreteCommand {
-receiver: Receiver
-state: any
+execute()
+undo()
}
class Invoker {
-commandHistory: Command[]
-currentCommand: Command
+setCommand(cmd: Command)
+executeCommand()
+undoCommand()
+redoCommand()
}
class Receiver {
-state: any
+action()
+undoAction()
+getState()
}
class Client {
+main()
}
Command <|.. ConcreteCommand : implements
ConcreteCommand --> Receiver : uses
Invoker o--> Command : stores
Client ..> Invoker : uses
Client ..> Receiver : creates
style Command fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
style ConcreteCommand fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
style Invoker fill:#fff3e0,stroke:#f57c00,stroke-width:2px
style Receiver fill:#fce4ec,stroke:#c2185b,stroke-width:2px
style Client fill:#f5f5f5,stroke:#616161,stroke-width:1px
交互演示
将请求封装为对象
InvokerRemote
命令队列
Receiver
⚫
OFF添加命令到队列,然后执行。命令模式将请求的发送者和接收者解耦。
生活类比
命令模式就像是餐厅点餐系统
餐厅点餐
服务员接受你的订单(命令),将其放入队列,厨师按顺序执行。你可以取消订单(撤销),也可以要求重做(重做)。
遥控器
电视遥控器上的每个按钮都是一个命令。按"开"按钮发送开灯命令,按"关"按钮发送关灯命令,还可以有"撤销"按钮撤销上一步操作。
文本编辑器
文本编辑器中的撤销/重做功能就是命令模式的典型应用。每次编辑操作都被封装为命令并保存到历史记录中。
代码实现
Example.java
实际应用
Java Runnable
Java 的 Runnable 接口是命令模式的典型应用,将可执行代码封装为对象。
Example.java
GUI 撤销/重做
文本编辑器、图像编辑软件中的撤销/重做功能通常使用命令模式实现。
Example.java
数据库事务
数据库事务管理使用命令模式来封装 SQL 操作,支持提交和回滚。
Example.java
练习
1
命令模式的主要目的是什么?
2
命令模式可以实现撤销和重做功能
3