命令模式
- 概念
- 类图
- 代码实例
概念
将一个请求(命令)封装成一个对象,从而具有不同请求(命令)供客户度选择,对请求排队、记录以及支持可重做和撤销操作
好处:
1、能很容易设计一个命令队列
2、很容易记录每个命令的日志
3、可以实现命令重做和撤销
4、在不修改已有类情况下,很容易添加新命令类
5、将请求一个操作对象和具体执行该操作的对象分离开,也就是下面讲到的将客户和烧烤人分开之间通过Waiter中间人来进行委派客户请求
并不是去猜测这些代码需要用命令模式来重构,但是敏捷开发原则告诉我们,一切需要基于现实,不要有任何猜测,那么后面需要有命令重做和撤销以及记录等功能时,再进行重构为命令模式才有意义。
类图
Waiter:服务员类(Invoker)
Command:命令抽象类(Command)
Barbecuer:命令接受者(Receiver)
BakeBeefCommand:烤牛肉命令(ConcreteCommand1)
BakeChickenWindCommand:烤鸡翅命令
BakeMuttonCommand:烤羊肉串命令
Client:测试类
代码实例
Waiter:服务员类
/**
* @author duanyimiao
* @create 2018-11-08 6:27 AM
* @description 服务员类,是客户和烧烤师傅之间中间类,降低客户和烧烤师傅之间耦合。也就是服务员代替客户发出命令
* <p>
* 1、(根据依赖倒置原则)服务员类需依赖一种抽象命令类,具体命令可以看做成菜单例如烤茄子、烤羊肉串等而具体命令中的操作需要委托烧烤人来执行
* <p>
* 2、记录客户发起的命令,也就是记录下单记录
* <p>
* 3、服务员批量将菜单交给烧烤师傅制作
* <p>
* 4、判断客户该命令请求是否能得到执行
* <p>
* 5、支持对未制作的菜进行撤销
**/
public class Waiter {
private List<Command> commands = new ArrayList<>();
//用于接受命令
public void setOrder(Command command) {
//假如鸡翅没有了
if (command instanceof BakeChickenWindCommand) {
System.out.println("sorry chicken wind was sold out");
return;
}
commands.add(command);
System.out.println("增加订单 " + command + " 时间 " + new Date());
}
public void cancelOrder(Command command) {
commands.remove(command);
System.out.println("取消订单 " + command + " 时间 " + new Date());
}
public void notifyToMake() {
for (Command command : commands) {
command.execute();
}
}
}
Command 抽象命令
/**
* @author duanyimiao
* @create 2018-11-08 6:38 AM
* @description 命令抽象类,命令实现委托于烧烤师傅
**/
public abstract class Command {
protected Barbecuer barbecuer;
public Command(Barbecuer barbecuer){
this.barbecuer = barbecuer;
}
public abstract void execute();
}
Barbecuer 命令接受者
/**
* @author duanyimiao
* @create 2018-11-08 6:40 AM
* @description 烧烤师傅,命令接受者
**/
public class Barbecuer {
public void bakeMutton(){
System.out.println("bake mutton");
}
public void bakeChickenWing(){
System.out.println("bake chicken wing");
}
public void bakeBeef(){
System.out.println("bake beef");
}
}
BakeBeefCommand 烤牛肉命令
/**
* @author duanyimiao
* @create 2018-11-08 6:50 AM
* @description 烤牛肉命令
**/
public class BakeBeefCommand extends Command{
public BakeBeefCommand(Barbecuer barbecuer){
super(barbecuer);
}
@Override
public void execute() {
//具体制作牛肉交给烧烤师傅进行处理
barbecuer.bakeBeef();
}
}
BakeChickenWindCommand 烤鸡翅命令
/**
* @author duanyimiao
* @create 2018-11-08 6:50 AM
* @description
**/
public class BakeChickenWindCommand extends Command {
public BakeChickenWindCommand(Barbecuer barbecuer){
super(barbecuer);
}
@Override
public void execute() {
//具体制作鸡翅交给烧烤师傅进行处理
barbecuer.bakeChickenWing();
}
}
BakeMuttonCommand 烤羊肉命令
/**
* @author duanyimiao
* @create 2018-11-08 6:50 AM
* @description
**/
public class BakeMuttonCommand extends Command{
public BakeMuttonCommand(Barbecuer barbecuer){
super(barbecuer);
}
@Override
public void execute() {
//具体制作羊肉交给烧烤师傅进行处理
barbecuer.bakeMutton();
}
}
Client:测试类
/**
* @author duanyimiao
* @create 2018-11-08 6:56 AM
* @description
**/
public class Client {
public static void main(String[] args) {
Barbecuer barbecuer = new Barbecuer();
Command bakeBeefCommand1 = new BakeBeefCommand(barbecuer);
Command bakeBeefCommand2 = new BakeBeefCommand(barbecuer);
Command bakeChickenWindCommand = new BakeChickenWindCommand(barbecuer);
Command bakeMuttonCommand1 = new BakeMuttonCommand(barbecuer);
Command bakeMuttonCommand2 = new BakeMuttonCommand(barbecuer);
Command bakeMuttonCommand3 = new BakeMuttonCommand(barbecuer);
Waiter waiter = new Waiter();
waiter.setOrder(bakeBeefCommand1);
waiter.setOrder(bakeBeefCommand2);
waiter.setOrder(bakeChickenWindCommand);
waiter.setOrder(bakeMuttonCommand1);
waiter.setOrder(bakeMuttonCommand2);
waiter.setOrder(bakeMuttonCommand3);
//撤销一个羊肉串
waiter.cancelOrder(bakeMuttonCommand3);
//重做羊肉串
waiter.setOrder(bakeMuttonCommand3);
waiter.notifyToMake();
}
}
输出结果:
增加订单 com.dynamo.command.BakeBeefCommand@108c4c35 时间 Wed Nov 28 11:37:31 CST 2018
增加订单 com.dynamo.command.BakeBeefCommand@4629104a 时间 Wed Nov 28 11:37:31 CST 2018
sorry chicken wind was sold out
增加订单 com.dynamo.command.BakeMuttonCommand@27f8302d 时间 Wed Nov 28 11:37:31 CST 2018
增加订单 com.dynamo.command.BakeMuttonCommand@4d76f3f8 时间 Wed Nov 28 11:37:31 CST 2018
增加订单 com.dynamo.command.BakeMuttonCommand@2d8e6db6 时间 Wed Nov 28 11:37:31 CST 2018
取消订单 com.dynamo.command.BakeMuttonCommand@2d8e6db6 时间 Wed Nov 28 11:37:31 CST 2018
增加订单 com.dynamo.command.BakeMuttonCommand@2d8e6db6 时间 Wed Nov 28 11:37:31 CST 2018
bake beef
bake beef
bake mutton
bake mutton
bake mutton