命令模式
二嫂的烧烤摊
大家好,我是小赵,现任藏剑山庄高级铸剑师,在山庄里任职的这段时间,和老王他们几个成了好朋友,经常一起吹牛逼打飞机。
今天周末,晚上八点左右,我们商量着去老王他二嫂那蹭一顿烧烤吃,老王的二嫂在山楂街通汇桥上摆了个烧烤摊,据说生意还不错,比我们上班强多了。
“老板娘,10串牛肉10串羊肉1斤小龙虾!羊肉不要辣!”
“老板娘,1个鸡腿2个鸡翅2串羊肉5串金针菇,羊肉不要辣!”
“老板娘,3串鸡胗5串香菇2串羊肉2串鸡肉,鸡肉不要辣,羊肉微辣!”
“老板娘,10串羊肉2个鸡腿3个鸡翅,羊肉中辣,其他微辣!”
...............
场面一度火爆,露天的小桌子都坐满了客人,点餐的点餐,催餐的催餐,老王二嫂一个人又负责点餐还负责烤菜,忙的天昏地暗。
“老赵,来几段代码玩玩。” 老王边嗑瓜子边说,老王就是这样,对我一本正经写的程序不感冒,反倒喜欢即兴表演,把眼前看到的事情用代码的方式写下来很有兴趣。
我想了想说:“那就写顾客点餐吧。”
类图:
我是老板娘:
public class Boss { public void orderMutton(){ System.out.println("烤一份羊肉"); } public void orderChicken(){ System.out.println("烤一份鸡肉"); } public void orderBeef(){ System.out.println("烤一份牛肉"); } }
主函数:
public static void main(String[] args) { User zhangsan = new User(); zhangsan.orderBeef(); zhangsan.orderChicken(); zhangsan.orderMutton(); }
输出:
烤一份牛肉
烤一份鸡肉
烤一份羊肉
“好了,写完了,大家看看,有什么问题?”。
“调用一个类的方法,这能看出个毛线?” 老王碎了一口瓜子皮。
“小王!过来帮忙!” 还没等我发作,老王二嫂的声音就朝这边喊了过来,估计那边实在是忙不过来了。
这不,老王嗑着瓜子屁颠屁颠的过去帮忙了。
老王的帮忙
有了老王的帮忙,二嫂顿时轻松了许多,只管烤菜,点餐的任务就交给老王了。
只见老王跑来跑去四处招呼,时不时的朝二嫂那边大喊:
“002桌一份牛肉!”
“005桌一份鸡肉!”
“005桌一份羊肉!”
“006桌一份羊肉!”
..........
老王完全对接了顾客和二嫂,成为了业务请求者和业务实现者的中间人,而顾客只需要对老王发送命令。
我想着想着,画下了流程图:
由于每一个菜品都是一个命令,所以命令应该是抽象出来,并且所有菜品的最终命令都是由老王传达给二嫂执行,所以命令都有一个通知执行操作。
那么我们的类图就可以这么画:
类图画好后,程序也就呼之欲出了:
我就是老王,我是调用者:
public class Invoker { private Command command; //记录命令 public void setCommand(Command command){ this.command = command; } //将命令发送给二嫂执行 public void action(){ this.command.execute(); } }
命令抽象:
public abstract class Command { protected Receiver receiver = new Receiver(); public abstract void execute();//执行命令 }
羊肉:
public class CommandMutton extends Command { @Override public void execute() { super.receiver.mutton(); } }
鸡肉:
public class CommandChicken extends Command { @Override public void execute() { super.receiver.chicken(); } }
牛肉:
public class CommandBeef extends Command { @Override public void execute() { super.receiver.beef(); } }
我是老板娘,是命令的接收者:
public class Receiver { public void mutton(){ System.out.println("烤一份羊肉"); } public void chicken(){ System.out.println("烤一份鸡肉"); } public void beef(){ System.out.println("烤一份牛肉"); } }
客户端:
public static void main(String[] args) { Invoker wang = new Invoker(); Command mutton = new CommandMutton(); wang.setCommand(mutton); wang.action(); }
输出:
烤一份羊肉
最后的干杯
老王忙完后我们摆了一桌胡吃海喝。
老刘把我的程序拿出来吹嘘说牛的一逼,结果老王一看,崩了两个字:“扯淡!”。
“我说老赵,你这写的啥玩意儿?点一份菜我就要通知一下二嫂?我嗓子还不喊哑了吗?”
这一问,我就陷入了沉默。
短暂的思索后,我改了一下Invoker类:
public class Invoker { private List<Command> list = new ArrayList<>(); //记录命令 public void setCommand(Command command){ this.list.add(command); } //撤销命令 public void removeCommand(Command command){ this.list.remove(command); } //将命令发送给二嫂执行 public void action(){ for(Command command : list){ command.execute(); } } }
客户端:
public static void main(String[] args) { Invoker wang = new Invoker(); Command mutton = new CommandMutton(); Command mutton2 = new CommandChicken(); wang.setCommand(mutton); wang.setCommand(mutton2); wang.action(); }
输出:
烤一份羊肉
烤一份鸡肉
老王一看,举起酒杯一饮而尽,赞叹道:“Perfect!”