设计模式--行为型--命令模式
命令模式
定义
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行存储,传递,调用,增加与管理。
结构
- 抽象命令类(Command)角色:定义命令的接口,声明执行的方法。
- 具体命令(Concrete Command)角色:具体的命令,实现命令接口;通常会持有接收者,并调用接受者的功能来完成命令要执行的操作。
- 接收者(Receiver)角色:接收者,真正执行命令的对象。任何一个类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
- 请求者(Invoke)角色:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个使客户端真正出发命令并要求命令执行相应操作的地方,也就是相当于使用命令对象的入口。
案例
饭店点餐:顾客把订单给服务员,服务员把订单给厨师,厨师做菜。
- 服务员:请求者,由她向厨师发起命令
- 厨师:接收者,真正执行命令的对象
- 订单:命令中包含订单
类图:
java
/**
* 抽象命令类
*/
public interface Command {
void execute();
}
java
/**
* 具体命令类
*/
public class OrderCommand implements Command{
// 持有接收者对象
private SeniorChef seniorChef;
private Order order;
public OrderCommand(SeniorChef seniorChef, Order order) {
this.seniorChef = seniorChef;
this.order = order;
}
@Override
public 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() + "卓的饭好了---");
}
}
java
/**
* 订单类
*/
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);
}
}
java
/**
* 厨师类
*/
public class SeniorChef {
public void makeFood(String name, int num){
System.out.println(num+"份"+name);
}
}
java
/**
* 服务员角色 请求者
*/
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();
}
}
}
}
java
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操作。命令模式可以与备忘录模式结合,实现命令的撤销与恢复。
- 缺点
- 使用命令模式可能会导致某些系统有过多的具体命令类。
- 系统结构更加复杂。
使用场景
- 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
- 系统需要在不同的时间指定请求,将请求排队和执行请求。
- 系统需要支持命令的撤销操作和恢复操作。