命令模式
程序员文章站
2022-05-26 08:39:25
...
1.命令模式的定义
将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或 记录请求日志,以及支持可 撤销的操作。
2.命令模式的结构和说明
- Command: 定义命令的接口,生命执行的方法
- ConcreteCommand: 命令接口实现对象,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
- Receiver: 接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现的相应功能。
- Invoker: 要求命令对象执行请求,通常 会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令执行相应操作的地方。
- Client: 创建具体的命令对象,并且设置命令对象的接收者。
相关代码如下:
- 接口的定义
/**
* 命令接口,声明执行的操作
*
* @author Administrator
*
*/
public interface Command {
/**
* 执行命令对应的操作
*/
public void execute();
}
2.具体的命令实现对象
/**
* 具体的命令 实现对象
*
* @author Administrator
*
*/
public class ConcreteCommand implements Command {
/**
* 持有相应的接收者对象
*/
private Receiver receiver;
/**
* 命令对象可以有自己的状态
*/
private String state;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
// 通常会转调接收者对象的相应方法,让接收者来真正执行 功能
receiver.action();
}
}
3. 接收者对象
/**
* 接收者对象
*
* @author Administrator
*
*/
public class Receiver {
/**
* 真正执行命令相应的操作
*/
public void action() {
// 真正执行命令操作的功能代码
}
}
4.Invoker对象
* 调用者
*
* @author Administrator
*
*/
public class Invoker {
private Command command = null;
public void setCommand(Command command) {
this.command = command;
}
/**
* 要求命令执行要求
*/
public void runCommand() {
// 调用命令对象的执行方法
command.execute();
}
}
5.Client 的实现
public class Client {
public static void main(String[] args) {
// 创建接收者
Receiver receiver = new Receiver();
// 创建命令对象,设定它的接收者
Command command = new ConcreteCommand(receiver);
// 创建Invoker,把命令对象设置进去
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.runCommand();
}
}
使用命令模式实现电脑开机的场景:
- 机箱上的按钮就相当于是命令对象
- 机箱相当于是Invoker
- 主板相当于接收者 对象
- 命令对象持有一个接收者对象,就相当于给机箱的按钮连上一根连接线
- 当机箱上的按钮被按下的时候,机箱就把这个命令通过连接线发送出去
主板类才是真正实现开机功能的地方,是真正执行命令的地方,也就是“接收者”。命令的实现对象,其实是个“虚”的实现,就如同那根连接线.
使用命令模式来实现示例的结构如下图:
- 定义主板接口类
/**
* 主板的接口
*
* @author Administrator
*
*/
public interface MainBorderApi {
/**
* 主板具有开机的功能
*/
public void open();
}
- 定义主板实现类
/**
* 技嘉主板类,开机命令的真正实现者,在Command模式中充当Receiver
*
* @author Administrator
*
*/
public class GigaMainBoard implements MainBorderApi {
/**
* 真正开机命令的实现
*/
@Override
public void open() {
System.out.println("技嘉主板现在正在开机摸清稍后");
System.out.println("接通电源.................");
System.out.println("设备检查..................");
System.out.println("装载系统...................");
System.out.println("机器正常运转起来...............");
System.out.println("机器已经正常打开,请操作...........");
}
}
- 定义命令接口和命令的实现
对于客户来说,开机就是按下按钮,别的什么都不想做,把用户的这个动作抽象一下,就相当于客户发出一个命令或者请求,其他的客户就不关心了。为描述客户的命令,现在定义出一个命令的接口,里面只有一个方法,那就是执行。示例代码如下;
/**
* 命令接口,声明执行的操作
*
* @author Administrator
*
*/
public interface Command {
/**
* 执行命令对应的操作
*/
public void execute();
}
/**
* 开机命令的实现,实现Command接口 持有开机命令的真正实现,通过调用接收者的方法来实现命令
*
* @author Administrator
*
*/
public class OpenCommand implements Command {
// 持有真正实现命令的接收者---主板对象
private MainBorderApi mainBoard;
public OpenCommand(MainBorderApi mainBoard) {
this.mainBoard = mainBoard;
}
@Override
public void execute() {
// 对于命令对象,根本不知道如何开机,会转调主板对象
// 让主板去完成开机的功能
this.mainBoard.open();
}
}
- 提供机箱
客户需要操作按钮,按钮是放置在机箱之上的,所以需要把机箱也定义出来。示例代码如下:
/**
* 机箱对象,本身有按钮,持有按钮对应的命令对象
*
* @author Administrator
*
*/
public class Box {
// 开机命令对象
private Command command;
public Box(Command command) {
super();
this.command = command;
}
/**
* 提供给客户使用,接收并响应用户请求,相当于按钮被按下出发的方法
*/
public void openButtonPresses() {
// 按下按钮,执行命令
this.command.execute();
}
}
- 客户使用按钮
public class Client {
public static void main(String[] args) {
// 1.把命令和真正的实现结合起来,相当于组装机器
// 把机箱桑按钮的联系那插接到主板上行
MainBorderApi mainBoard = new GigaMainBoard();
OpenCommand openCommand = new OpenCommand(mainBoard);
// 2.为机箱上的按钮设置对应的命令,让按钮知道该干什么
Box box = new Box(openCommand);
box.openButtonPresses();
}
}
结果如下:
推荐阅读