设计模式--行为型--命令模式
- 命令模式
- 定义
- 结构
- 案例
- 优缺点
- 使用场景
命令模式
定义
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行存储,传递,调用,增加与管理。
结构
- 抽象命令类(Command)角色:定义命令的接口,声明执行的方法。
- 具体命令(Concrete Command)角色:具体的命令,实现命令接口;通常会持有接收者,并调用接受者的功能来完成命令要执行的操作。
- 接收者(Receiver)角色:接收者,真正执行命令的对象。任何一个类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
- 请求者(Invoke)角色:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个使客户端真正出发命令并要求命令执行相应操作的地方,也就是相当于使用命令对象的入口。
案例
饭店点餐:顾客把订单给服务员,服务员把订单给厨师,厨师做菜。
- 服务员:请求者,由她向厨师发起命令
- 厨师:接收者,真正执行命令的对象
- 订单:命令中包含订单
类图:
/*** 抽象命令类*/
public interface Command {void execute();
}
/*** 具体命令类*/
public class OrderCommand implements Command{// 持有接收者对象private SeniorChef seniorChef;private Order order;public OrderCommand(SeniorChef seniorChef, Order order) {this.seniorChef = seniorChef;this.order = order;}@Overridepublic void execute() {System.out.println(order.getDiningTable() + "卓的订单:");Map<String, Integer> foodDir = order.getFoodDir();Set<String> keys = foodDir.keySet();for (String foodName : keys){seniorChef.makeFood(foodName,foodDir.get(foodName));}System.out.println(order.getDiningTable() + "卓的饭好了---");}
}
/*** 订单类*/
public class Order {// 餐桌号码private int diningTable;// 餐品及数量private Map<String, Integer> foodDir = new HashMap<>();public int getDiningTable() {return diningTable;}public void setDiningTable(int diningTable) {this.diningTable = diningTable;}public Map<String, Integer> getFoodDir() {return foodDir;}public void setFoodDir(Map<String, Integer> foodDir) {this.foodDir = foodDir;}public void setFood(String name, int num) {foodDir.put(name, num);}
}
/*** 厨师类*/
public class SeniorChef {public void makeFood(String name, int num){System.out.println(num+"份"+name);}
}
/*** 服务员角色 请求者*/
public class Waitor {// 持有多个命令private List<Command> commands = new ArrayList<>();public List<Command> getCommands() {return commands;}public void setCommands(Command command) {commands.add(command);}// 发起命令的方法public void orderUp(){System.out.println("服务员说:新订单来了");for (Command command : commands) {if (command != null){command.execute();}}}
}
public class Test01 {public static void main(String[] args) {// 订单对象Order order = new Order();order.setDiningTable(1);order.setFood("炒土豆丝",1);order.setFood("可乐",1);Order order1 = new Order();order1.setDiningTable(2);order1.setFood("面条", 1);// 厨师对象SeniorChef seniorChef = new SeniorChef();// 创建命令对象OrderCommand orderCommand = new OrderCommand(seniorChef, order);OrderCommand orderCommand1 = new OrderCommand(seniorChef, order1);// 创建调用者,服务员Waitor waitor = new Waitor();waitor.setCommands(orderCommand);waitor.setCommands(orderCommand1);// 发起命令waitor.orderUp();}
}
优缺点
- 优点
- 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
- 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,满足开闭原则,对扩展比较灵活。
- 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
- 方便实现Undo和Redo操作。命令模式可以与备忘录模式结合,实现命令的撤销与恢复。
- 缺点
- 使用命令模式可能会导致某些系统有过多的具体命令类。
- 系统结构更加复杂。
使用场景
- 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
- 系统需要在不同的时间指定请求,将请求排队和执行请求。
- 系统需要支持命令的撤销操作和恢复操作。