设计模式(19)命令模式
一、介绍:
1、定义:命令模式(Command Pattern)是一种行为设计模式,它将请求封装为一个对象,从而使你可以使用不同的请求对客户端进行参数化。命令模式还支持请求的排队、记录日志、撤销操作等功能。
2、组成结构:
(1)命令接口(Command):定义执行命令的方法,可以是抽象类或接口。
public interface Command {
void execute();
}
(2)具体命令类(Concrete Command):实现命令接口,封装了具体的请求和接收者,负责执行请求。
/**
* 具体的命令实现
*/
public class ConcreteCommand implements Command {
/**
* 持有相应的接收者对象
*/
private Receiver receiver = null;
/**
* 构造方法,传入相应的接收者对象
*
* @param receiver 相应的接收者对象
*/
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
/**
* 执行命令
*/
@Override
public void execute() {
// 通常会转调接收者对象的相应方法,让接收者来真正执行功能
receiver.action();
}
}
(3)接收者类(Receiver):命令接受者对象,定义了命令接受者可以做的事情。执行实际的操作,命令对象将请求委托给接收者来执行。
public class Receiver {
public void action() {
System.out.println("执行具体操作");
}
}
(4)调用者类(Invoker):Invoker类是具体命令的接收者,用于接收客户的所有命令,然后将命令转达给执行者,执行这些命令。
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}
客户端(Client):创建具体的命令对象,并将其分配给调用者来执行。
public class Client {
public static void main(String[] args) {
// 创建接收者
Receiver receiver = new Receiver();
// 创建命令对象,设定它的接收者
Command command = new ConcreteCommand(receiver);
// 创建调用者,把命令对象设置进去
Invoker invoker = new Invoker();
invoker.setCommand(command);
// 调用者调用命令
invoker.executeCommand();
}
}
3、优点
- 能够比较容易的设计一个命令队列
- 在需要的情况下,可以比较容易地将命令记入日志
- 允许接收请求的一方决定是否要解决请求
- 可以容易的实现对请求的撤销和重做
- 容易扩展新的命令类
- 能够把请求一个操作的对象,与知道怎么执行一个操作的对象分隔开
二、demo:
1、点餐:服务员充当命令委托角色,在顾客和厨师之间松耦合
(1)命令:
//顾客抽象命令
public abstract class Command {
public Integer count;
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
protected Cook receiver;
public Command(Cook receiver,int count) {
this.receiver = receiver;
this.count = count;
}
public abstract void execute();
}
//具体命令1
public class BakeBeefCommand extends Command {
public BakeBeefCommand(Cook receiver,int count) {
super(receiver,count);
}
@Override
public void execute() {
receiver.bakeBeef();
}
}
//具体命令2
public class BakeMuttonCommand extends Command{
public BakeMuttonCommand(Cook receiver,int count) {
super(receiver,count);
}
@Override
public void execute() {
receiver.bakeMutton();
}
}
(2)命令实际接收者 厨师
public class Cook {
public void bakeMutton(){
System.out.println("烤羊肉");
}
public void bakeBeef(){
System.out.println("烤牛肉");
}
}
(3)命令中转 服务员
public class Waiter {
private List<Command> orders= new ArrayList<>();
public void setOrder(Command command) {
if(command.getCount() < 5){
System.err.println("点餐失败,一份数量最小为5,count="+command.getCount());
}else{
System.out.println("点餐成功,记录日志,count="+command.getCount());
this.orders.add(command);
}
}
public void cancleOrder(Command command) {
System.out.println("取消成功,记录日志,count="+command.getCount());
this.orders.remove(command);
}
public void executeCommand(){
System.out.println("***点餐结束***");
for (Command comm : orders) {
comm.execute();
}
}
}
客户端
public static void main(String[] args) {
Cook receiver = new Cook();
Waiter waiter = new Waiter();
Command muttonCommand = new BakeMuttonCommand(receiver,1);
waiter.setOrder(muttonCommand);
muttonCommand = new BakeMuttonCommand(receiver,5);
waiter.setOrder(muttonCommand);
Command beefCommand = new BakeBeefCommand(receiver,6);
waiter.setOrder(beefCommand);
beefCommand = new BakeBeefCommand(receiver,7);
waiter.setOrder(beefCommand);
//临时取消
waiter.cancleOrder(beefCommand);
//全部点餐结束后执行
waiter.executeCommand();
}
输出:
点餐失败,一份数量最小为5,count=1
点餐成功,记录日志,count=5
点餐成功,记录日志,count=6
点餐成功,记录日志,count=7
取消成功,记录日志,count=7
***点餐结束***
烤羊肉
烤牛肉