文章目录
- 1、命令模式
- 2、案例
- 3、总结
1、命令模式
餐厅点餐:
创建一个厨师对象,让服务员对象调用厨师对象中的方法进行点餐通知,当后面厨师换人,服务员类的代码也要修改,耦合 + 不符合开闭。理想状态:服务员将订单放柜台,不用关注是哪个厨师去做。厨师照着订单做菜,不用关注哪个服务员放的。
⇒
将发出请求和责任 和 执行请求的责任分割开,并将请求封装成一个命令对象,二者通过命令对象进行沟通。
主要角色:
- 抽象命令类
- 具体命令类:聚合接收者对象
- 接收者:执行命令的对象
- 请求者:上面例子中的服务员对象,聚合抽象命令类的对象
2、案例
实现上面的点餐案例:
定义订单类,模拟一点业务信息,包含餐桌号、所下餐品的名字和份数
public class Order {
// 餐桌号码
private int diningTable;
// 用来存储餐名并记录份数,key为餐名,value为份数
private Map<String, Integer> foodDic = new HashMap<String, Integer>();
public int getDiningTable() {
return diningTable;
}
public void setDiningTable(int diningTable) {
this.diningTable = diningTable;
}
public Map<String, Integer> getFoodDic() {
return foodDic;
}
//直接往空map放数据
public void setFoodDic(String name, int num) {
foodDic.put(name,num);
}
}
定义厨师类:
// 资深大厨类 是命令的Receiver
public class SeniorChef {
//制作食物
public void makeFood(int num,String foodName) {
System.out.println(num + "份" + foodName);
}
}
定义抽象命令类,定义一个执行命令的方法:
public interface Command {
void execute();//只需要定义一个统一的执行方法
}
定义具体的命令类,聚合接收者对象(厨师对象),调用接收者类的方法来干活儿:
public class OrderCommand implements Command {
//持有接受者对象
private SeniorChef receiver;
private Order order;
public OrderCommand(SeniorChef receiver, Order order){
this.receiver = receiver;
this.order = order;
}
@Override
public void execute() {
System.out.println(order.getDiningTable() + "桌的订单:");
Set<String> keys = order.getFoodDic().keySet();
for (String key : keys) {
receiver.makeFood(order.getFoodDic().get(key),key); //调用执行者的方法
}
try {
Thread.sleep(100);//停顿一下 模拟做饭的过程
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(order.getDiningTable() + "桌的饭弄好了");
}
}
定义服务员类(请求者),聚合多个命令对象:
public class Waitor {
private ArrayList<Command> commands;//可以持有很多的命令对象
public Waitor() {
commands = new ArrayList(); //无参构造中直接初始化一个空集合
}
public void setCommand(Command cmd){
commands.add(cmd); //set时,不set一个List,直接往List存元素
}
// 发出命令 喊 订单来了,厨师开始执行
public void orderUp() {
System.out.println("美女服务员:叮咚,大厨,新订单来了.......");
for (int i = 0; i < commands.size(); i++) {
Command cmd = commands.get(i);
if (cmd != null) { //健壮性
cmd.execute();
}
}
}
}
定义客户端:
public class Client {
public static void main(String[] args) {
//创建2个order
Order order1 = new Order();
order1.setDiningTable(1); //1号桌
order1.getFoodDic().put("西红柿鸡蛋面",1);
order1.getFoodDic().put("小杯可乐",2);
Order order2 = new Order();
order2.setDiningTable(3); //3号桌
order2.getFoodDic().put("尖椒肉丝盖饭",1);
order2.getFoodDic().put("小杯雪碧",1);
//创建接收者
SeniorChef receiver=new SeniorChef();
//将订单和接收者封装成命令对象
OrderCommand cmd1 = new OrderCommand(receiver, order1);
OrderCommand cmd2 = new OrderCommand(receiver, order2);
//创建调用者 waitor
Waitor waitor = new Waitor();
waitor.setCommand(cmd1);
waitor.setCommand(cmd2);
//将订单带到柜台 并向厨师喊 订单来了
waitor.orderUp();
}
}
运行:
3、总结
适用场景:
- 需要将调用者和请求者解耦,使二者不直接交互(如服务员类调用命令类,命令类里调用接收者)
- 结合备忘录模式,支持命令的撤销和恢复操作