命令模式
定义
命令模式(Command):将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
UML
对象说明
Command:用来声明执行操作的接口
ConcreteCommand:将一个接受者对象绑定于一个动作,调用接受者相应的操作,以实现excute()
Invoke:要求该命令执行这个请求。
Receiver:知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者。
Client:创建一个具体命令对象并设定它的接收者。
Demo
在这里我们以我们日常生活中在路边摊吃烧烤和在烧烤店里面吃烧烤对比:在烧烤摊的时候,往往老板和服务员都是一个人,在人多起来的时候,老板往往会自顾不暇,有极大的可能会导致出现错误。这个是因为老板与客户是直接产生了关系,耦合性高。当我们在烧烤店里面点烧烤的时候,我们可以直接通过服务员的关系,将我们所需要吃的烧烤的内容直接告诉服务员,让服务员去和后台的烧烤师傅相联系,每个桌子都有一张菜单,后台的烧烤师傅可以直接根据服务员所提供的菜单进行操作。当然,当我们不需要某份烧烤的时候,也可以通过服务员,让师傅取消这份烧烤。接下来我们就是模拟在烧烤店点烧烤的过程:
首先是命令类:
abstract public class BaseCommand { protected Barbecuer receiver; /** * 抽象命令类,只是需要确定"烤肉串者是谁" * */ public BaseCommand(Barbecuer receiver){ this.receiver=receiver; } /** * 执行命令 * */ public abstract void excuteCommand(); }
具体的命令类:
public class BakeChickenWingCommand extends BaseCommand{ public BakeChickenWingCommand(Barbecuer receiver) { super(receiver); } @Override public void excuteCommand() { receiver.bakeChickenWing(); } }
public class BakeMuttonCommand extends BaseCommand { public BakeMuttonCommand(Barbecuer receiver) { super(receiver); } @Override public void excuteCommand() { receiver.bakeMutton(); } }
服务员(Invoke)
public class Waiter { private BaseCommand command; /** * 设置订单,设置订单的时候也可以加上判断,表示receiver是否接受这个命令 * */ public void setOrder(BaseCommand baseCommand){ this.command=baseCommand; } /** * 可以设置一个ArrayList来存储命令和删除命令 */ /** * 通知执行 * */ public void notifyReceiver(){ command.excuteCommand(); } }
执行烤肉命令的人:
public class Barbecuer { /** * 执行烤羊肉的命令 * */ public void bakeMutton(){ System.out.println("烤羊肉串"); } /** * 执行烤鸡翅的命令 * */ public void bakeChickenWing(){ System.out.println("烤鸡翅"); } }
Client:
public class Client { public static void main(String[] args) { //开店前的准备 Barbecuer boy=new Barbecuer(); BaseCommand bakeMuttonCommand=new BakeMuttonCommand(boy); BaseCommand bakeMuttonCommand2=new BakeMuttonCommand(boy); BaseCommand bakeChickenWingCommand=new BakeChickenWingCommand(boy); Waiter girl=new Waiter(); //open the shop //通知烤肉 girl.setOrder(bakeMuttonCommand); girl.notifyReceiver(); girl.setOrder(bakeMuttonCommand2); girl.notifyReceiver(); girl.setOrder(bakeChickenWingCommand); girl.notifyReceiver(); } }
小结
命令模式的优点:
-
它能较为容易的设计一个命令队列;
-
在需要的情况下,可以较为容易的将命令记入日志
-
允许接收请求的一方决定是否否决请求;
-
可以容易的实现对请求的撤销和重做;
-
由于加进新的具体命令类不影响其他的类,因此增加新的距离命令较为容易;
-
命令模式最为关键的优点就是把请求一个操作的对象与知道怎么执行一个操作的对象分割开。