? 命令模式允许将请求封装成一个对象(命令对象,包含执行操作所需地所有信息),并将命令对象按照一定的顺序存储在队列中,然后再逐一调用执行,这些命令可以支持反向操作,进行撤销和重做。这样发送者就只需要触发命令就可以完成操作,不需要知道接受者的具体操作,从而实现两者间的解耦
? 在餐饮业中,命令模式可以用于实现订单的处理流程。例如在餐厅中,当我们在客户端或者小程序上进行点单,客户端 / 小程序会将我们在上面下的订单请求封装成为一个对象,通过发送命令给后厨的工作人员上,而他们就会根据我们下的具体订单进行菜品备菜、菜品制作、菜品上菜等一系列操作。
package com.technologystatck.designpattern.mode.command;
import java.util.*;
public class Commands {
public static void main(String[] args) {
Receiver receiver = new Receiver();
ConcreteCommand command = new ConcreteCommand(receiver);
new Invoker(command).executeCommand();
}
}
//定义执行操作的接口,包含一个execute方法,有时还会包括unExecute方法,表示撤销命令
interface Command{
//执行方法
void execute();
//撤销方法
void undo();
}
//实现命令接口,执行具体的操作
class ConcreteCommand implements Command{
//接收者对象
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
@Override
public void undo() {
receiver.unAction();
}
}
//定义接受者类,知道如何实施与执行一个请求相关的操作
class Receiver{
public void action(){
//执行操作
}
public void unAction(){
//撤销操作
}
}
//定义调用者类,调用命令对象执行请求
class Invoker{
private Command command;
public Invoker(Command command) {
this.command = command;
}
public void executeCommand(){
command.execute();
}
}
//调用者类可以维护一个命令队列或者撤销栈,以支持批处理和撤销命令
class Invoker{
//命令队列
private Queue<Command> commandQueue;
//撤销栈
private Stack<Command> undoStack;
public Invoker(Queue<Command> commandQueue, Stack<Command> undoStack) {
this.commandQueue = new LinkedList<>();
this.undoStack = new Stack<>();
}
//设置命令并执行
public void setAndExecuteCommand(Command command){
command.execute();
commandQueue.offer(command);
undoStack.push(command);
}
//撤销上一个命令
public void undoLastCommand(){
if(!undoStack.isEmpty()){
Command lastCommand = undoStack.pop();
//命令类实现undo方法
lastCommand.undo();
commandQueue.remove(lastCommand);
}else{
System.out.println("No command to undo.");
}
}
//执行命令队列中的所有命令
public void executeCommandsInQueue(){
for (Command command : commandQueue) {
command.execute();
}
}
}
小明去奶茶店买奶茶,他可以通过在自助点餐机上来点不同的饮品,请你使用命令模式设计一个程序,模拟这个自助点餐系统的功能。
输出执行完所有点单后的制作情况,每行输出一种饮品的制作情况。如果制作完成,输出 “XXX is ready!”,其中 XXX 表示饮品名称。
package com.technologystatck.designpattern.mode.command;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//创建接收者和命令对象
DrinkMaker drinkMaker = new DrinkMaker();
//读取命令数量
int nums=scanner.nextInt();
scanner.nextLine();
while(nums-- > 0){
//读取命令
String drinkName=scanner.next();
//创建命令对象
OrderCommand command = new OrderCommand(drinkName, drinkMaker);
//执行命令
OrderMachine orderMachine = new OrderMachine();
orderMachine.setCommand(command);
orderMachine.executeOrder();
}
scanner.close();
}
}
//定义执行操作的命令订单接口
interface Command{
void execute();
}
//定义具体命令类实现点餐
class OrderCommand implements Command{
//饮料名称
private String drinkName;
//具体的饮料制作者
private DrinkMaker drinkMaker;
public OrderCommand(String drinkName, DrinkMaker drinkMaker) {
this.drinkName = drinkName;
this.drinkMaker = drinkMaker;
}
@Override
public void execute() {
drinkMaker.makeDrink(drinkName);
}
}
//接收者类-制作饮料
class DrinkMaker{
public void makeDrink(String drinkName){
System.out.println(drinkName+" is ready!");
}
}
//调用者类-点餐机
class OrderMachine{
private Command command;
public void setCommand(Command command) {
this.command = command;
}
//执行下单方法
public void executeOrder(){
command.execute();
}
}