目录
一、命令模式介绍
1.1 命令模式定义
1.2 命令模式原理
1.2.1 命令模式类图
1.2.2 模式角色说明
二、命令模式的应用
2.1 需求说明
2.2 需求实现
2.2.1 抽象命令接口
2.2.2 订单类
2.2.3 厨师类
2.2.4 服务员类
2.2.5 具体命令类
2.2.6 测试类
三、命令模式总结
3.1 命令模式的优点
3.2 命令模式的缺点
3.3 命令模式的使用场景
命令模式(command pattern)的定义: 命令模式将请求(命令)封装为一个对象,这样可以使用不同的请求参数化其他对象(将不同请求依赖注入到其他对象),并且能够支持请求(命令)的排队执行、记录日志、撤销等 (附加控制)功能。
命令模式的核心是将指令信息封装成一个对象,并将此对象作为参数发送给接收方去执行,达到使命令的请求与执行方解耦,双方只通过传递各种命令对象来完成任务。
在实际的开发中,如果你用到的编程语言并不支持用函数作为参数来传递,那么就可以借助命令模式将函数封装为对象来使用。
我们知道,C语言支持函数指针,我们可以把函数当作变量传递来传递去。但是,在大部分编程语言中,函数没法儿作为参数传递给其他函数,也没法儿赋值给变量。借助命令模式,我们可以将函数封装成对象。具体来说就是,设计一个包含这个函数的类,实例化一个对象传来传去,这样就可以实现把函数像对象一样使用。
命令模式包含以下主要角色:
模拟酒店后厨的出餐流程,来对命令模式进行一个演示,命令模式角色的角色与案例中角色的对应关系如下:
package main.java.cn.test.command.V1;
/**
* @author ningzhaosheng
* @date 2024/1/15 17:42:27
* @description 抽象命令接口
*/
public interface Command {
//只需要定义一个统一的执行方法
void execute();
}
package main.java.cn.test.command.V1;
import java.util.HashMap;
import java.util.Map;
/**
* @author ningzhaosheng
* @date 2024/1/15 17:40:57
* @description 订单类
*/
public class Order {
//餐桌号码
private int diningTable;
//存储菜名与份数
private Map foodMenu = new HashMap<>();
public int getDiningTable() {
return diningTable;
}
public void setDiningTable(int diningTable) {
this.diningTable = diningTable;
}
public Map getFoodMenu() {
return foodMenu;
}
public void setFoodDic(Map foodMenu) {
this.foodMenu = foodMenu;
}
}
package main.java.cn.test.command.V1;
/**
* @author ningzhaosheng
* @date 2024/1/15 17:41:47
* @description 厨师类 -> Receiver角色
*/
public class Chef {
public void makeFood(int num, String foodName) {
System.out.println(num + "份," + foodName);
}
}
package main.java.cn.test.command.V1;
import java.util.ArrayList;
/**
* @author ningzhaosheng
* @date 2024/1/15 17:44:20
* @description 服务员-> Invoker调用者
*/
public class Waiter {
//可以持有很多的命令对象
private ArrayList commands;
public Waiter() {
commands = new ArrayList();
}
public Waiter(ArrayList commands) {
this.commands = commands;
}
public void setCommands(Command command) {
commands.add(command);
}
//发出命令 ,指挥厨师工作
public void orderUp() {
System.out.println("服务员: 叮咚,有新的订单,请厨师开始制作......");
for (Command cmd : commands) {
if (cmd != null) {
cmd.execute();
}
}
}
}
package main.java.cn.test.command.V1;
import java.util.Set;
/**
* @author ningzhaosheng
* @date 2024/1/15 17:42:55
* @description 具体命令
*/
public class OrderCommand implements Command {
//持有接收者对象
private Chef receiver;
private Order order;
public OrderCommand(Chef receiver, Order order) {
this.receiver = receiver;
this.order = order;
}
@Override
public void execute() {
System.out.println(order.getDiningTable() + "号桌的订单: ");
Set keys = order.getFoodMenu().keySet();
for (String key : keys) {
receiver.makeFood(order.getFoodMenu().get(key), key);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(order.getDiningTable() + "号桌的菜已上齐.");
}
}
package main.java.cn.test.command.V1;
/**
* @author ningzhaosheng
* @date 2024/1/15 17:45:22
* @description 测试类
*/
public class Test {
public static void main(String[] args) {
Order order1 = new Order();
order1.setDiningTable(1);
order1.getFoodMenu().put("鲍鱼炒饭", 1);
order1.getFoodMenu().put("茅台迎宾", 1);
Order order2 = new Order();
order2.setDiningTable(3);
order2.getFoodMenu().put("海参炒面", 1);
order2.getFoodMenu().put("五粮液", 1);
//创建接收者
Chef receiver = new Chef();
//将订单和接收者封装成命令对象
OrderCommand cmd1 = new OrderCommand(receiver, order1);
OrderCommand cmd2 = new OrderCommand(receiver, order2);
//创建调用者
Waiter invoke = new Waiter();
invoke.setCommands(cmd1);
invoke.setCommands(cmd2);
//将订单发送到后厨
invoke.orderUp();
}
}
好了,本次分享就到这里,欢迎大家继续阅读《设计模式》专栏其他设计模式内容,如果有帮助到大家,欢迎大家点赞+关注+收藏,有疑问也欢迎大家评论留言!