本文作者:程序员飞云
1. 什么是命令模式?
命令模式(Command): 将一个请求分装成一个对象,从而可以使用不同的请求对客户进行参数化;对于请求排队或者请求日志,以及支持可撤销的操作。
主要是将客户端和执行请求的对象解耦。
举个常见的两个例子
一个是我们生活中使用遥控器来控制电视,我们控制遥控器(相当于客户端),点击遥控按钮*(命令)来控制电视( 执行请求的对象),即使遥控器坏了也没用影响,可以使用新的遥控器,但是电视坏了,遥控器就没用了。
另一个是去烧烤店点单,我们告诉服务员,通过点单命令来告诉烧烤师傅 要考什么肉,而这个服务员是谁我们不关心,这个服务员忙,我们可以找另一个服务员。( 这个例子不大适合小的烧烤店,一般老板一个人就包了2个人的工作)
2. 优点
- 可以容易设计一个命令队列
- 容易的将一些命令写入日志
- 允许接收请求的一方决定是否拒绝请求
- 容易实现对请求的撤销和重做
- 加入了新的命令类不影响其他的类 6解耦了请求者以及接收者,系统更加灵活
3. 使用场景
- 操作多种的复杂操作,比如排队,请求日志,记录操作,撤消重做等等
- 系统需要增加新的命令不影响之前的功能,或者处理复杂的组合命令
4. 案例一:遥控器—电视
1. 接受者: 电视
最终执行命令的对象,知道具体的相关操作
这里就设置一个电视的电视名字字段,有两个功能开启电视,关闭电视
/** * 接收者,电视设备 */public class Device { private String name;
public Device(String name) { this.name = name; }
public void on() { System.out.println("开启: " + this.name); }
public void off() { System.out.println("关闭: " + this.name); }}2. 命令Command
相当于总的遥控器按钮制定的规范,这个命令才是控制电视开关的核心
public interface Command { void execute(); // 执行命令}3. 开启按钮的命令
/** * 开启命令 */public class TurnOnCommand implements Command { private Device device;
public TurnOnCommand(Device device) { this.device = device; }
@Override public void execute() { device.on(); }}4. 关闭按钮的命令
/** * 关闭命令 */public class TurnOffCommand implements Command { private Device device;
public TurnOffCommand(Device device) { this.device = device; }
@Override public void execute() { device.off(); }}5. 调用者
遥控器点击按钮后,如果是开,就是执行的TurnOnCommand命令,然后命令执行里面的execute
/** * 遥控器 */public class RemoteControl { private Command command;
public void setCommand(Command command) { this.command=command; }
/** * 按下按钮 */ public void buttonWasPressed() { command.execute(); }}6. 客户端
用户操作,点击遥控器
需要对应的电视,按钮,操作。
public class Client { public static void main(String[] args) { // 电视 Device device = new Device("TCL");
// 遥控器 RemoteControl remoteControl = new RemoteControl();
// 对电视发布命令 TurnOnCommand turnOnCommand = new TurnOnCommand(device);
// 执行命令 remoteControl.setCommand(turnOnCommand);
// 响应结果 remoteControl.buttonWasPressed(); }}7. 进阶 :记录历史
这个操作其实还算简单,就是使用一个集合来存放对应的命令
/** * 遥控器 */public class RemoteControl { private Command command;
private List<Command> commands = new ArrayList<>();
public void setCommand(Command command) { this.commands.add(command); this.command = command; }
/** * 按下按钮 */ public void buttonWasPressed() { command.execute(); }
public void buttonHistory() { for (Command command : commands) { command.execute(); } }}8. 进阶:显示一系列操作
public class Client { public static void main(String[] args) { // 电视 Device device = new Device("TCL"); // 遥控器 RemoteControl remoteControl = new RemoteControl(); // 对电视发布命令 TurnOnCommand turnOnCommand = new TurnOnCommand(device); TurnOffCommand turnOffCommand = new TurnOffCommand(device); TurnOnCommand turnOnCommand2 = new TurnOnCommand(device); // 执行命令 remoteControl.setCommand(turnOnCommand); remoteControl.setCommand(turnOffCommand); remoteControl.setCommand(turnOnCommand2); // 响应结果 remoteControl.buttonWasPressed(); System.out.println("------------"); // 操作历史 remoteControl.buttonHistory(); }}9. 运行截图

10. uml图

5. 案例二:烤肉串师傅—服务员
1. 接收者: 烤肉串师傅
具有考鸡翅和考羊肉的功能
/** * 烤肉师傅 */public class Barbecuer {
public void bakeMutton() { System.out.println("烤羊肉串"); }
public void bakeChickenWing() { System.out.println("烤鸡翅"); }}2. 命令Command
执行命令
public interface Command { void execute(); // 执行命令}3. 具体命令
烤羊肉命令
/** * 烤羊肉命令 */public class BakeMuttonCommand implements Command { private Barbecuer barbecuer;
public BakeMuttonCommand(Barbecuer barbecuer) { this.barbecuer = barbecuer; }
@Override public void execute() { barbecuer.bakeMutton(); }}烤鸡翅命令
/** * 烤鸡翅命令 */public class BakeChickenWingCommand implements Command { private Barbecuer barbecuer;
public BakeChickenWingCommand(Barbecuer barbecuer) { this.barbecuer = barbecuer; }
@Override public void execute() { barbecuer.bakeChickenWing(); }}4. 调用者–服务员
服务员发送相关的命令
/** * 服务员 */public class Waiter { //持有命令对象 private Command command;
public void setCommand(Command command) { this.command = command; }
public void action() { command.execute(); }}5. 客户端–用户
public class Client { public static void main(String[] args) { // 烤肉师傅 Barbecuer barbecuer = new Barbecuer();
// 服务员 Waiter waiter = new Waiter();
// 点菜命令 BakeChickenWingCommand bakeChickenWingCommand = new BakeChickenWingCommand(barbecuer);
// 服务员接受命令 waiter.setCommand(bakeChickenWingCommand);
// 反馈 waiter.action(); }}如果想要实现记录历史可以仿照前面的,还可以实现移除订单等等相关操作。
评论