举个栗子
路边摊吃烧烤,老板只有一人,又要记住点单,又要忙着收费,客户做什么都要排队。。。
反例思路1
如果客户多了,请求多,就容易混乱,他叫五串羊肉串,你叫三个烤鸡翅,老板哪里忙得过来。代码中的体现就是一句一句输出,所以应该要有个服务员。。。
门面改造
Talk is cheap, show me the code
(屁话少说,放码过来)
/**
* 抽象命令
* Created by callmeDevil on 2019/12/14.
*/
public abstract class Command {
protected Barbecuer receiver;
public Command(Barbecuer receiver){
this.receiver = receiver;
}
// 执行命令
public abstract void excuteCommand();
}
/**
* 烤羊肉串命令
* Created by callmeDevil on 2019/12/14.
*/
public class BakeMuttonCommand extends Command{
public BakeMuttonCommand(Barbecuer receiver){
super(receiver);
}
@Override
public void excuteCommand() {
receiver.bakeMutton();
}
}
/**
* 烤鸡翅命令
* Created by callmeDevil on 2019/12/14.
*/
public class BakeChickenWingCommand extends Command{
public BakeChickenWingCommand(Barbecuer receiver){
super(receiver);
}
@Override
public void excuteCommand() {
receiver.bakeChickenWing();
}
}
/**
* 烤肉串者
* Created by callmeDevil on 2019/12/14.
*/
public class Barbecuer {
public void bakeMutton(){
System.out.println("烤羊肉串!");
}
public void bakeChickenWing(){
System.out.println("烤鸡翅!");
}
}
/**
* 服务员
* Created by callmeDevil on 2019/12/14.
*/
public class Waiter {
private Command command;
// 不管什么用户想要什么烤肉,反正都是命令,只管记录订单,然后通知烤肉串者即可
public void setOrder(Command command){
this.command = command;
}
public void notifying(){
command.excuteCommand();
}
}
public class Test {
public static void main(String[] args) {
// 开店前的准备
Barbecuer boy = new Barbecuer();
Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);
Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);
BakeChickenWingCommand bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
Waiter girl = new Waiter();
// 开门营业
girl.setOrder(bakeMuttonCommand1);
girl.notifying();
girl.setOrder(bakeMuttonCommand2);
girl.notifying();
girl.setOrder(bakeChickenWingCommand1);
girl.notifying();
}
}
运行结果
烤羊肉串!
烤羊肉串!
烤鸡翅!
其实服务员那里可以完善,比如点单的时候不是一个一个点,而是点完之后一起给单;而且尚未烤肉时,订单也可以进行更改或取消,烤肉的人也是很多肉一起烤,等等,此处就不优化了。
命令模式
定义
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
UML图
总结
- 它能较容易的设计一个命令队列
- 在需要的情况下,可以较容易的将命令记入日志
- 允许接收请求的一方决定是否要取消请求
- 可以容易的实现对请求的撤销和重做
- 由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易
- 最关键的就是命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开(服务员和烤肉串者)。
是否碰到如撤销/恢复功能等类似的情况就一定要实现命令模式?
敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只要在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。