命令模式
说明
命令模式(Command Pattern)属于行为型模式,是将一个请求封装为对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
无论是在现实生活中还是软件系统中,交流是无处不在的,而交流其实就是对命令的请求与处理的过程。当命令的请求者与处理者是一对一或者小规模的多对一时,他们之间的紧耦合是没问题的。但如果是大规模的多对一请求时,对请求命令的管理就成为了需要,否则会造成处理者对请求处理的紊乱,而如果将管理请求命令的职责交给处理者,那么处理者的职责会过于繁重,这时就需要命令模式来管理命令,从而将命令的请求者与处理者进行解耦。
本质:解耦命令请求与处理。
结构
命令模式主要角色如下:
Command(抽象命令角色):定义了执行命令的接口;
ConcreteCommand(具体命令角色):继承/实现Command,实现执行命令的接口,并且需要绑定一个Receiver对象;
Invoker(命令的请求方):命令的请求方,需要定义一个Command的引用,用于接收客户端的命令,并且可以对命令进行管理(记录日志等);
Receiver(命令的接收者):处理具体的命令。
代码案例
Receiver(命令的接收者)
/**
* @program: command
* @description: 命令的接收者
* @author: wxw
* @create: 2024-03-11 12:07
**/
public class Receiver {
public void buyWahaha(String name, Integer count){
System.out.println("帮" + name + "购买" + count + "瓶哇哈哈!");
}
public void buyHotDog(String name, Integer count){
System.out.println("帮" + name + "购买" + count + "根热狗!");
}
public void buyBread(String name, Integer count){
System.out.println("帮" + name + "购买" + count + "包面包!");
}
}
Command(抽象命令角色)
/**
* @program: command
* @description: 命令接口
* Command(抽象命令角色)
* @author: wxw
* @create: 2024-03-11 11:51
**/
public abstract class BuyCommand {
protected String name;
protected Integer count;
protected Receiver receiver;
public BuyCommand(String name, Integer count, Receiver receiver) {
this.name = name;
this.count = count;
this.receiver = receiver;
}
public abstract String returnCommandName();
public abstract void execute();
}
ConcreteCommand(具体命令角色)
/**
* @program: command
* @description: 购买哇哈哈
* ConcreteCommand(具体命令角色)
* @author: wxw
* @create: 2024-03-11 12:03
**/
public class BuyWahaha extends BuyCommand {
public BuyWahaha(String name, Integer count, Receiver receiver) {
super(name, count, receiver);
}
@Override
public String returnCommandName() {
return Commodity.WAHAHA.desc;
}
@Override
public void execute() {
receiver.buyWahaha(name,count);
}
}
/**
* @program: command
* @description: 购买热狗
* ConcreteCommand(具体命令角色)
* @author: wxw
* @create: 2024-03-11 12:05
**/
public class BuyHotDog extends BuyCommand {
public BuyHotDog(String name, Integer count, Receiver receiver) {
super(name, count, receiver);
}
@Override
public String returnCommandName() {
return Commodity.HOT_DOG.desc;
}
@Override
public void execute() {
receiver.buyHotDog(name,count);
}
}
/**
* @program: command
* @description: 购买面包
* ConcreteCommand(具体命令角色)
* @author: wxw
* @create: 2024-03-11 12:05
**/
public class BuyBread extends BuyCommand {
public BuyBread(String name, Integer count, Receiver receiver) {
super(name, count, receiver);
}
@Override
public String returnCommandName() {
return Commodity.BREAD.desc;
}
@Override
public void execute() {
receiver.buyBread(name,count);
}
}
Receiver(命令的接收者)
/**
* @program: command
* @description: 命令请求者
* @author: wxw
* @create: 2024-03-11 12:11
**/
public class Invoker {
private List<BuyCommand> commandList = new ArrayList<>();
// 接收客户端命令
public void receiveRequest(BuyCommand command) {
logRecord(command);
commandList.add(command);
}
// 记录日志
private void logRecord(BuyCommand command){
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sf.format(new Date()) + "记录:" + command.name
+ "需要购买" + command.returnCommandName() + ",数量:" + command.count);
}
// 答应详细清单
public void detailedList(){
System.out.println("==============购物清单==============");
Iterator<BuyCommand> iterator = commandList.iterator();
while(iterator.hasNext()){
BuyCommand command = iterator.next();
System.out.println(command.name + ":商品名称:" + command.returnCommandName() + ",数量:" + command.count);
}
}
// 批量执行
public void sendRequestBatch(){
System.out.println("===============发送请求==============");
Iterator<BuyCommand> iterator = commandList.iterator();
while(iterator.hasNext()){
BuyCommand command = iterator.next();
command.execute();
}
}
}
枚举常量类
/**
* @program: command
* @description: 商品枚举
* @author: wxw
* @create: 2024-03-11 15:24
**/
public enum Commodity {
WAHAHA("哇哈哈"),
HOT_DOG("热狗"),
BREAD("面包")
;
String desc;
Commodity(String desc) {
this.desc = desc;
}
}
客户端
public class Test {
public static void main(String[] args) {
// 命令请求者
Invoker invoker = new Invoker();
// 命令接收者
Receiver receiver = new Receiver();
// 张三需要购买2瓶哇哈哈
invoker.receiveRequest(new BuyWahaha("张三", 2, receiver));
// 李四需要购买1瓶哇哈哈
invoker.receiveRequest(new BuyWahaha("李四", 1, receiver));
// 张三需要购买1根热狗
invoker.receiveRequest(new BuyHotDog("张三", 1, receiver));
// 李四需要购买1包面包
invoker.receiveRequest(new BuyBread("李四", 1, receiver));
// 打印购物清单
invoker.detailedList();
// 发送命令请求
invoker.sendRequestBatch();
}
}
输出结果
2024-03-11 16:11:05记录:张三需要购买哇哈哈,数量:2
2024-03-11 16:11:05记录:李四需要购买哇哈哈,数量:1
2024-03-11 16:11:05记录:张三需要购买热狗,数量:1
2024-03-11 16:11:05记录:李四需要购买面包,数量:1
==============购物清单==============
张三:商品名称:哇哈哈,数量:2
李四:商品名称:哇哈哈,数量:1
张三:商品名称:热狗,数量:1
李四:商品名称:面包,数量:1
===============发送请求==============
帮张三购买2瓶哇哈哈!
帮李四购买1瓶哇哈哈!
帮张三购买1根热狗!
帮李四购买1包面包!