十六、命令模式
命令模式,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求
日志,以及支持可撤销的操作。 ——摘自《大话设计模式》
Ps:“将请求封装为对象”的思想即是该种设计模式的精华。
基本结构如下:
①、Receiver,命令的接收者,也是命令的实际执行者
具体方法一
具体方法二
……
②、Command,命令超类
Receiver 的引用
execute() 命令的执行方法,子类覆写该方法
③、ConcreteCommand,具体的命令,继承Command
concreteExcute() 覆写超类的 execute() 方法
根据实际情况调用 Receiver 的某个具体方法,覆写之前会为 Receiver 的引用赋值
④、Invoker,请求者,提供给外界用于命令的下达、取消、记录、组合等
Command 的引用
setCommand() 下达命令的方法
cancelCommand() 取消命令的方法
notifyExcute() 通知命令执行的方法
示例代码: 以顾客点烧烤为例
①、Receiver #########################################
/** *烤肉串者,Receiver(命令的接受者,也是最终执行命令的角色) */public class Barbecuer {//烤羊肉public void bakeMutton(){System.out.println("烤羊肉开始……");}//烤鸡翅public void bakeChickenWing(){System.out.println("烤鸡翅开始……");}}
②、Command #########################################
/** *命令的超类,该模式的核心 */public abstract class Command {protected Barbecuer receiver; //命令的接收者public Command(Barbecuer receiver){this.receiver = receiver;}public abstract void excuteCommand();}
③、ConcreteCommand #########################################
/** *烤羊肉命令,具体命令一 */public class BakeMuttonCommand extends Command {public BakeMuttonCommand(Barbecuer receiver) {super(receiver);}@Overridepublic void excuteCommand() { //覆写命令执行,调用receiver的烤羊肉方法this.receiver.bakeMutton();}@Overridepublic String toString() { //覆写toString方法,便于记录return "羊肉一串";}}
/** *烤鸡翅命令,具体命令二 */public class BakeChickenWing extends Command {public BakeChickenWing(Barbecuer receiver) {super(receiver);}@Overridepublic void excuteCommand() { //覆写命令执行,调用receiver的烤鸡翅方法this.receiver.bakeChickenWing();}@Overridepublic String toString() { //覆写toString方法,便于记录return "鸡翅一串";}}
④、Invoker #########################################
/** *服务员,记录、撤销命令并通知执行 */public class Waiter {private List<Command> commandList = new ArrayList<Command>(); //命令集合//添加订单public void setCommand(Command command){commandList.add(command);System.out.println("添加订单:"+command.toString()+","+new Date());}//取消订单public void cancelCommand(Command command){commandList.remove(command);System.out.println("取消订单:"+command.toString()+","+new Date());}//通知命令执行public void notifyExcute(){for(Command command:commandList){command.excuteCommand();}}}
测试方法:
public class Test {public static void main(String[] args) throws Exception {Barbecuer duke = new Barbecuer(); //厨师dukeCommand command1 = new BakeMuttonCommand(duke); //烤羊肉命令,指定厨师Command command2 = new BakeChickenWing(duke); //烤鸡翅命令,指定厨师Waiter ming = new Waiter(); //服务员小明ming.setCommand(command1); //记录命令一ming.setCommand(command2); //记录命令二ming.cancelCommand(command2); //取消命令二ming.notifyExcute(); //下单结束,通知厨师开始烧烤}}
测试结果:
添加订单:羊肉一串,Fri Oct 18 09:33:21 CST 2013
添加订单:鸡翅一串,Fri Oct 18 09:33:21 CST 2013
取消订单:鸡翅一串,Fri Oct 18 09:33:21 CST 2013
烤羊肉开始……