命令模式将一个请求封装为一个对象, 使得发出请求的责任和执行请求的责任分隔开, 这样两者之间通过命令对象进行沟通, 这样方便将命令对象进行存储, 传递, 调用, 增加与管理

命令模式结构

  • 抽象命令类: 定义命令的接口, 声明执行命令的方法
  • 具体命令类: 具体命令, 实现命令接口; 通常会持有接收者, 并调用接收者的功能来完成命令要执行的操作
  • 实现者: 接收者, 真正执行命令的对象. 任何类都可以成为一个接收者, 只要它能够实现命令要求实现的功能
  • 请求者: 要求命令对象执行请求, 通常持有命令对象. 它是使用命令对象的入口

命令模式实现

我们假设有一家餐厅, 客户需要向服务员点单, 服务员再把点单信息提交给厨师.

// 订单类
public class Order {
private int tableNum;

private Map<String, Integer> foodDir = new HashMap<>();

public void setTableNum(int tableNum) {
this.tableNum = tableNum;
}

public void setFoodDir(String food, int num) {
foodDir.put(food, num);
}

public int getTableNum() {
return tableNum;
}

public Map<String, Integer> getFoodDir() {
return foodDir;
}
}

// 厨师类
public class Chef {
public void makeFood(String name, int num) {
System.out.println("Chef makes" + num + name);
}
}

// 命令接口
public interface Command {
void execute();
}

// 具体命令类
public class OrderCommand implements Command {
// 持有接收者对象
private Chef receiver;
private Order order;

public OrderCommand(Chef chef, Order order) {
this.chef = chef;
this.order = order;
}

public void execute() {
Map<String, Integer> foodDir = order.getFoodDir();
Set<String> keys = foodDir.keySet();
for (String foodName : keys) {
receiver.makeFood(foodName, foodDir.get(foodName));
}
}
}

// 请求者类
public class Waiter {
// 持有多个命令对象
private List<Command> commands = new ArrayList<>();

public void setCommand(Command cmd) {
command.add(cmd);
}

public void orderUp() {
for (Command command : commands) {
if (command != null) {
command.excute();
}
}
}
}

public class Client {
public static void main(String[] args) {
Order order1 = new Order();
order1.setTableNum(1);
order1.setFoodDir("Cola", 1);

Order order2 = new Order();
order2.setTableNum(2);
order2.setFoodDir("Fenta", 2);

Chef chef = new Chef();
OrderCommand cmd1 = new OrderCommand(chef, order1);
OrderCommand cmd2 = new OrderCommand(chef, order2);

Waiter waiter = new Waiter();
waiter.setCommand(cmd1);
waiter.setCommand(cmd2);
// 发起命令
waiter.orderUp();
}
}

优点:

  • 降低系统的耦合度, 命令模式能将调用操作的对象和执行操作的对象相互解耦
  • 增加或删除命令非常方便
  • 可以实现宏指令, 命令模式能和组合模式相结合, 将多个命令装配成一个命令, 即宏指令
  • 方便实现 undo 和 redo 操作

缺点:

  • 使用命令模式会导致系统有过多的实现类
  • 系统复杂度提高