概念
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分隔开。这两者之间通过命令对象进行沟通,即可方便将命令对象进行存储、传递、调用、增加与管理
结构
抽象命令角色:定义命令需要实现的接口方法
具体命令角色:实现抽象命令角色的接口方法,通常会持有接收者角色对象,并调用接收者角色对象的方法来完成命令要执行的操作
实现者/接收者角色:执行命令具体功能的对象
调用者/请求者角色:要求命令对象执行请求,通常会持有命令对象,并且一个请求者角色对象可以同时持有多个命令对象
示例
目标:顾客去餐馆吃饭,要吃西红柿炒蛋、外婆菜肉末。现服务员(请求者)得到顾客想吃的菜品后,记录到订单本(命令角色)上,交由厨师(接收者)根据订单本进行炒菜
抽象者/接收者角色
packake 设计模式.行为型模式.命令模式;
/**
* 厨师:实现者/接收者角色
*/
public class Chef {
/**
* 煮饭菜
*/
public void cooking(String name) {
System.out.println("正在做:" + name);
}
}
抽象命令角色
package 设计模式.行为型模式.命令模式;
/**
* 抽象命令:抽象命令角色
*/
public abstract class Command {
/**
* 执行命令
*/
public abstract void execute();
}
具体命令角色
package 设计模式.行为型模式.命令模式;
/**
* 堆代码 duidaima.com
* 订单命令:具体命令角色
*/
public class OrderCommand extends Command {
// 厨师:接收者对象
private Chef receiver;
// 饭菜名称
private String name;
/**
* 构造函数
*/
public OrderCommand(Chef receiver, String name) {
this.receiver = receiver;
this.name = name;
}
/**
* 执行命令
*/
@Override
public void execute() {
// 执行接收者方法
this.receiver.cooking(this.name);
}
}
调用者/请求者角色
package 设计模式.行为型模式.命令模式;
import java.util.ArrayList;
import java.util.List;
/**
* 服务员:调用者/请求者角色
*/
public class Waiter {
// 拥有的命令:可以有多个,所以用List保存
List<Command> commandList = new ArrayList<>();
/**
* 添加命令
*/
public void addCommand(Command command) {
this.commandList.add(command);
}
/**
* 执行订单
*/
public void executeOrder() {
for (Command command : commandList) {
command.execute();
}
}
}
测试类
package 设计模式.行为型模式.命令模式;
/**
* 测试类
*/
public class Demo {
public static void main(String[] args) {
// 创建接收者:厨师
Chef chef = new Chef();
// 创建命令
OrderCommand command1 = new OrderCommand(chef, "西红柿炒蛋");
OrderCommand command2 = new OrderCommand(chef, "外婆菜肉末");
// 创建请求者:服务员
Waiter waiter = new Waiter();
// 添加命令
waiter.addCommand(command1);
waiter.addCommand(command2);
// 开始执行
waiter.executeOrder();
}
}
优缺点
优点
1.降低了系统的耦合度,将调用者对象与接收者对象解耦
2.增删命令非常方便,不会影响到其他类,满足“开闭原则”
3.可以与组合模式结合,将多个命令装配成一个组合命令,实现宏命令
4.与备忘录模式结合,可以很方便地实现Undo和Redo操作,进行命令的撤销与恢复
缺点
1.可能会导致某些系统有过多的具体命令类
2.系统结构更多复杂
应用场景
1.系统需要将请求调用者与请求接收者解耦、使调用者与接收者不直接交互时,可以使用命令模式
2.系统需要在不同的时间指定请求,将请求排队和执行请求时,可以使用命令模式
3.系统需要支持命令的撤销操作和恢复操作时,可以使用命令模式