命令模式
命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
Command类,抽象命令类。ConcreteCommand具体命令类。
Receiver,接受者类,用于执行一个请求操作。
Invoker类,要求该命令执行这个请求。
命令类
//抽象命令类
abstract class Command {
// 命令的接受者
protected Receiver receiver;
public Command(Receiver receiver){
this.receiver = receiver;
}
//执行命令
public abstract void excuteCommand();
}
//具体命令类
class ConcreteCommand extends Command{
public ConcreteCommand(Receiver receiver){
super(receiver);
}
public void excuteCommand(){
receiver.action();
}
}
Receiver
class Receiver{
public void action(){
System.out.println("执行请求!");
}
}
Invoker
class Invoker{
private Command command;
public void setCommand(Command command){
this.command = command;
}
public void executeCommand(){
command.excuteCommand();
}
}
客户端
public class Test {
public static void main(String[] args) {
System.out.println("**********************************************");
System.out.println("《大话设计模式》代码样例");
System.out.println();
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.executeCommand();
System.out.println();
System.out.println("**********************************************");
}
}
命令模式的应用
饭店点餐。
服务员负责记录点餐,通知厨师。厨师负责做(执行)。命令就是点的餐。
命令类
//抽象命令类
abstract class Command {
protected Barbecuer receiver;
public Command(Barbecuer receiver){
this.receiver = receiver;
}
//执行命令
public abstract void excuteCommand();
}
//烤羊肉命令类
class BakeMuttonCommand extends Command{
public BakeMuttonCommand(Barbecuer receiver){
super(receiver);
}
public void excuteCommand(){
receiver.bakeMutton();
}
}
//烤鸡翅命令类
class BakeChickenWingCommand extends Command{
public BakeChickenWingCommand(Barbecuer receiver){
super(receiver);
}
public void excuteCommand(){
receiver.bakeChickenWing();
}
}
Barbecuer类(请求的接受者)
//烤肉串者
class Barbecuer{
//烤羊肉
public void bakeMutton(){
System.out.println("烤羊肉串!");
}
//烤鸡翅
public void bakeChickenWing(){
System.out.println("烤鸡翅!");
}
}
服务员类
class Waiter{
private ArrayList<Command> orders = new ArrayList<Command>();
//设置订单
public void setOrder(Command command){
String className=command.getClass().getSimpleName();
if (className.equals("BakeChickenWingCommand")){
System.out.println("服务员:鸡翅没有了,请点别的烧烤。");
}
else{
this.orders.add(command);
System.out.println("增加订单:"+className+" 时间:"+getNowTime());
}
}
//取消订单
public void cancelOrder(Command command){
String className=command.getClass().getSimpleName();
orders.remove(command);
System.out.println("取消订单:"+className+" 时间:"+getNowTime());
}
//通知执行
public void notifyCommand(){
for(Command command : orders){
command.excuteCommand();
}
}
private String getNowTime(){
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
return formatter.format(new Date()).toString();
}
}
客户端
public class Test {
public static void main(String[] args) {
System.out.println("**********************************************");
System.out.println("《大话设计模式》代码样例");
System.out.println();
// 开店前的准备
Barbecuer boy = new Barbecuer();// 烤肉厨师
Command bakeMuttonCommand1 = new BakeMuttonCommand(boy); // 烤羊肉串
Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy); // 烤鸡翅
Waiter girl = new Waiter(); // 服务员
System.out.println("开门营业,顾客点菜");
girl.setOrder(bakeMuttonCommand1); // 下单烤羊肉串
girl.setOrder(bakeMuttonCommand1); // 下单烤羊肉串
girl.setOrder(bakeMuttonCommand1); // 下单烤羊肉串
girl.setOrder(bakeMuttonCommand1); // 下单烤羊肉串
girl.setOrder(bakeMuttonCommand1); // 下单烤羊肉串
girl.cancelOrder(bakeMuttonCommand1); // 取消一串羊肉串订单
girl.setOrder(bakeChickenWingCommand1); // 下单烤鸡翅
System.out.println("点菜完毕,通知厨房烧菜");
girl.notifyCommand(); // 通知厨师
System.out.println();
System.out.println("**********************************************");
}
}
命令模式总结
命令模式的优点
- 能比较容易地设计一个命令队列。
- 在需要的情况下,可以较容易地将命令记入日志。
- 允许接收请求的一方决定是否要否决请求。
- 可以容易地实现对请求的撤销和重做。
- 加进新的具体的命令类不影响其他的类。
- 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。
敏捷开发原则:不要为代码添加基于猜测的 ,实际不需要的功能。
如果不清楚一个系统是否需要命令模式,一般不要着急实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。