描述
- 把请求封装为一个对象,把请求和执行请求的责任分开。两者之间通过命令对象进行沟通,方便命令对象进行存储,传递,管理。
- 比如:客户找服务员订单点餐 ,服务员发送订单命令给厨师。对服务员和厨师之间的解耦。
- 在请求里面实现业务调用。接收者和调用者之间的耦合。
角色
- 抽象命名角色:命令的接口,声明。
- 具体命令角色:实现抽象命令角色,发送具体要执行的命令,通常持有接收者。
- 接收者(实现者):执行命令的对象。(厨师)
- 调用者(请求者):客户端调用命令的入口,通常持有命令对象。(服务员)
实现
public class Test {
public static void main(String[] args) {
Order order1 = new Order();
order1.setTableNo("1号桌");
order1.setMenu("佛跳墙", 1);
order1.setMenu("米饭", 2);
Order order2 = new Order();
order2.setTableNo("3号桌");
order2.setMenu("蛋炒饭", 2);
order2.setMenu("苦瓜羹", 2);
Cook cook1 = new Cook();
Cook cook2 = new Cook();
OrderCommand command = new OrderCommand(order1, cook1);
OrderCommand command2 = new OrderCommand(order2, cook2);
Waitor waitor = new Waitor();
waitor.setCommand(command);
waitor.setCommand(command2);
waitor.placeRrder();
}
}
class Order {
private String tableNo;
private Map<String, Integer> menuList = new HashMap<>();
public String getTableNo() {
return tableNo;
}
public void setTableNo(String tableNo) {
this.tableNo = tableNo;
}
public Map<String, Integer> getMenuList() {
return menuList;
}
public void setMenu(String dish, Integer num) {
this.menuList.put(dish, num);
}
}
class Cook {
void cooking(String dish, Integer num) {
System.out.println("烹制:" + num + "份" + dish);
}
}
interface Command {
void execute();
}
class OrderCommand implements Command {
private Cook cook;
private Order order;
public OrderCommand(Order order, Cook cook) {
this.cook = cook;
this.order = order;
}
@Override
public void execute() {
System.out.println("命令执行了:开始烹饪:");
order.getMenuList().forEach((key, val) -> {
cook.cooking(key, val);
});
System.out.println("执行完毕");
}
}
class Waitor {
private List<Command> commandList = new ArrayList<>();
public void setCommand(Command command) {
this.commandList.add(command);
}
public void placeRrder() {
System.out.println("您的订单来了------");
commandList.forEach(item -> {
if (Objects.nonNull(item)) {
item.execute();
}
});
System.out.println("订单完成------");
}
}
优点
- 降低接收者和调用者之间的耦合度。
- 满足开闭原则,增加或删除一个命令,不会影响其它类。
- 与组合模式结合,可实现宏命令(多个命令装配成一个)。
- 方便实现undo 和 redo 操作。(与备忘录结合实现:撤销恢复操作)
缺点
- 可能导致会有过多的具体命令类。
- 系统结构变得复杂了。
使用场景
- 请求调用者和接收者解耦(不直接交互)。
- 需要在不同时间指定请求,请求排队执行(队列)。
- 需支持撤销undo操作和恢复redo操作。
JDK中的应用
public class Test {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Runnable runnable = new Runnable() {
@Override
public void run() {
receiver.say();
}
};
new Thread(runnable).start();
}
}
class Receiver {
void say() {
System.out.println("接收者");
}
}