命令模式
经营烧烤的两种模式
很多人都喜欢吃烧烤,尤其是东北人民,在东北没有什么是一顿烧烤解决不了的,如果有那就两顿。咳咳,开个玩笑。现在,在对象城吃货街有一个烧烤摊,经营的是一个烧烤师傅,他烧烤的手艺很好周围有一群吃货围着,大家七嘴八舌的点着餐。忽然,发生了争吵,原来是小明很久之前就点了5串羊肉,2串面筋,但是师傅却把刚刚烤好的羊肉给了旁边刚来的小王,小明很不开心的跟师傅理论起来了,但是师傅实在太忙,已经是手忙脚乱了。一边烧烤,一边听吃客点菜,一边还得收钱,根本忙不过来,且记不住。离烧烤摊点不远处,有一个龙哥烧烤店,他们家来了食客后,服务员都会递一份菜单给食客,然后食客点完菜之后,再告诉服务员,服务员再把订单交给厨房里的大师傅,当某种食材售罄时,还会提醒食客取消或替换,食客在等待的过程中,如果想减少某样菜的数量告知服务员一声即可。这两种经营模式,显然是第二种更加的高效且不易犯错,服务员起到了隔绝食客直接调用师傅的过程,让师傅只专注于自己核心的烧烤业务。前者为灵活性很差的紧耦合设计,后者为更灵活的松耦合设计。
类图如下:
什么是命令模式?
将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
代码
Command类,用来执行操作的,可以抽象类也可以是接口
public abstract class Command { Receiver receiver; public Command(Receiver receiver){ this.receiver = receiver; } public abstract void execute(); }
ConcreteCommand类,将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现execute
public class ConcreteCommand extends Command { public ConcreteCommand(Receiver receiver) { super(receiver); } public void execute() { receiver.action(); } }
Invoker类,要求该命令执行这个请求
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand(){
command.execute();
}
}
Receiver类,知道如何实施与执行一个请求相关的操作,任何类都可能成为一个接收者
public class Receiver { public void action(){ System.out.println("执行请求"); } }
创建一个具体的命令对象,并设定它的接收者。
public static void main(String[] args){ Receiver r = new Receiver(); Command c = new ConcreteCommand(r); Invoker i = new Invoker(); i.setCommand(c); i.executeCommand(); }
总结
- 命令模式可以容易的地设计一个命令队列
- 在需要的情况下,可以很容易的将命令记入日志
- 允许接受请求的一方决定是否要否决请求
- 可以实现对请求的撤销和重做
- 由于加进新的具体命令类不影响其他的类吗,因此增加新的具体命令类很容易
- 命令模式将请求一个操作对象和知道怎么执行一个操作对象分割开,实现了解耦。这是最重要的一点