行为型模式——命令模式
命令模式概述
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分隔开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行存储、传递、调用与管理。
命令模式结构
命令模式包括以下角色:
- **抽象命令类角色:**定义命令的接口,声明执行的方法。
- **具体命令角色:**具体的命令,实现命令接口;通常会持有接受者,并调用接受者的功能来完成命令要执行的操作。
- **实现者/接受者角色:**接收者,真正执行命令的对象。任何类都可能成为一个接受者,只要它能实现命令要求实现的功能。
- **调用者/请求者角色:**要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正出发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
命令模式实现
以一个客人点单,服务员接单,大厨做饭的例子实现以下命令模式。在这个例子中,client相当于会生成的具体命令,client将具体命令存放在Waiter的ArrayList中,client调用任务的execute方法要求任务开始执行,在任务开始执行后,任务的execute方法中,调用了SeniorChef的makefood方法。
也就是说命令模式的特点是:**调用者/请求者调用命令的方法,命令调用实现者/接受者的方法。**一个一个的传递下去。
/**
* Commend是抽象命令类角色
*/
public interface Commend {
void execute();
}
/**
* OrderCommend具体命令类角色
*/
public class OrderCommend implements Commend{
private SeniorChef seniorChef;
private Order order;
public OrderCommend(SeniorChef seniorChef, Order order) {
this.seniorChef = seniorChef;
this.order = order;
}
@Override
public void execute() {
System.out.println(order.getDiningTable() + "桌的订单:");
Set<String> keys = order.getFoodDic().keySet();
for (String key : keys) {
seniorChef.makeFood(order.getFoodDic().get(key),key);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(order.getDiningTable() + "桌的饭做好啦");
}
}
/**
* SeniorChef类是实现者/接受者角色
*/
public class SeniorChef {
public void makeFood(int num,String foodName){
System.out.println(num + "份" + foodName);
}
}
/**
* Waiter类调用者/请求者角色
*/
public class Waiter {
private ArrayList<Commend> commands;
public Waiter(){
commands = new ArrayList<>();
}
public void setCommend(Commend commend) {
commands.add(commend);
}
public void orderUp(){
System.out.println("美女服务员:叮咚,大厨,新订单来了。。。。。。");
for (int i=0;i<commands.size();i++){
Commend cmd = commands.get(i);
if (cmd != null){
cmd.execute();
}
}
}
}
/**
* Order类是辅助类
*/
public class Order {
private int diningTable;
private Map<String,Integer> foodDic = new HashMap<>();
public int getDiningTable(){
return diningTable;
}
public void setDiningTable(int diningTable){
this.diningTable = diningTable;
}
public Map<String,Integer> getFoodDic(){
return foodDic;
}
public void setFoodDic(String name,int num){
foodDic.put(name,num);
}
}
/**
* Client类相当于测试类
*/
public class Client {
public static void main(String[] args) {
Order order1 = new Order();
order1.setDiningTable(1);
order1.getFoodDic().put("西红柿鸡蛋面",1);
order1.getFoodDic().put("小杯可乐",2);
Order order2 = new Order();
order2.setDiningTable(3);
order2.getFoodDic().put("青椒盖饭",1);
order2.getFoodDic().put("小杯雪碧",1);
SeniorChef seniorChef = new SeniorChef();
OrderCommend orderCommend1 = new OrderCommend(seniorChef,order1);
OrderCommend orderCommend2 = new OrderCommend(seniorChef,order2);
Waiter invoker = new Waiter();
invoker.setCommend(orderCommend1);
invoker.setCommend(orderCommend2);
invoker.orderUp();
}
}
命令模式优缺点
优点:
- 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
- 增加或删除命令非常方便。采用命令模式增加和删除命令不影响其他类,他满足“开闭原则”,对扩展比较灵活。
- 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
- 方便实现Undo、Redo操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。
缺点:
- 使用命令模式可能会导致某些系统有过多的具体命令类
- 系统结构更加复杂。
文章内容为个人学习总结,如有错误望指正。
参考链接https://www.bilibili.com/video/BV1Np4y1z7BU