4.2 命令模式
-
模式动机与定义
- 模式动机
-
生活中
- 相同的开关可以通过不同的电线来控制不同的电器
- 开关 <- -> 请求发送者
- 电器 <- -> 请求的最终接收者和处理者
- 开关和电器之间并不存在直接耦合关系,它们通过电线连接在一起,使用不同的电线可以连接不同的请求接收者
-
软件开发
- 按钮 <- -> 请求发送者
- 事件处理类 <- -> 请求的最终接收者和处理者
- 发送者和接收者之间引入了新的命令对象(类似电线),将发送者的请求封装在命令对象中,再通过命令对象来调用接收者的方法
- 相同的按钮可以对应不同的事件处理类
-
- 模式定义
- 命令模式(Command Pattern): 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
- 命令模式是一种对象行为型模式,其别名为动作(Action)模式或事物(Transaction)模式
- 模式动机
-
模式结构与分析
- 模式结构
- 包含角色:
- Command:抽象命令类
- ConcreteCommand:具体命令类
- Invoker:调用者
- Receiver:接收者
- 包含角色:
- 模式分析
- 将请求的发送者和接收者完全解耦
- 发送者和接收者之间没有直接引用关系
- 发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求
- 命令模式的本质是对请求进行封装
- 一个请求对应于一个命令,将发出命令的责任和执行命令的责任分开
- 模式结构
-
模式实例与解析
- 模式实例
- 模式解析
-
模式效果与应用
-
模式优点
- 降低系统的耦合度
- 新的命令可以很容易地加入到系统中,符合开闭原则
- 可以比较容易地设计一个命令队列或宏命令(组合命令)
- 为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案
-
模式缺点
- 使用命令模式可能会导致某些系统有过多的具体命令类(针对每一个对请求接收者的调用操作都需要设计一个具体命令类)
-
模式应用
- 需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互
- 需要在不同的时间指定请求,将请求排队和执行请求
- 需要支持命令的撤销操作和恢复操作
- 需要将一组操作组合在一起形成宏命令
-
interface Command {
public void excute();
}
class Television {
void open() {
System.out.println("TV open");
}
void close() {
System.out.println("TV close");
}
}
class TVCloseCommand implements Command {
private Television tv;
public TVCloseCommand() {
// TODO Auto-generated constructor stub
tv = new Television();
}
@Override
public void excute() {
tv.close();
// TODO Auto-generated method stub
}
}
class TVOpenCommand implements Command {
Television tv;
public TVOpenCommand() {
// TODO Auto-generated constructor stub
tv = new Television();
}
@Override
public void excute() {
// TODO Auto-generated method stub
tv.open();
}
}
class Controller {
private Command openCommand, closeCommand;
public Controller(Command openCommand,Command closeCommand) {
// TODO Auto-generated constructor stub
this.closeCommand = closeCommand;
this.openCommand = openCommand;
}
void open() {
openCommand.excute();
}
void close() {
closeCommand.excute();
}
}