命令模式:将请求封装为对象,从而使你可用不同的请求对象进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
我们经常出去吃饭,有时候碰见路边摊,我们直接可以和老板说我们要点什么东西,下面为实现代码
厨师类
public class Cook { public void cookChicken(){ System.out.println("制作红烧鸡!"); } public void cookRice(){ System.out.println("制作米饭!"); } }
测试类
public class Test { public static void main(String[] args) { Cook cook = new Cook(); cook.cookChicken(); cook.cookChicken(); cook.cookRice(); } }
测试结果:
制作红烧鸡!
制作红烧鸡!
制作米饭!
可以看到,消费者和厨师是紧耦合的,如果消费者增多,那么订单也就越来越多,厨师就可能记不住那多么订单,并且也有可能记错,而且顾客也不应该关注厨师的制作流程,所以我们从日常生活中可以看到,稍微大一些的饭店都会有服务员来记录每桌的订单,从而使顾客和厨师松耦合,让厨师专注自己的事——料理。下面为增加服务员的代码:
//厨师 public class Cook { public void cookChicken(){ System.out.println("制作红烧鸡!"); } public void cookRice(){ System.out.println("制作米饭!"); } }
//命令接口 public interface Command { void executeCommand(); }
//制作烧鸡的命令 public class CookChickenCommand implements Command { private Cook cook; public CookChickenCommand(Cook cook){ this.cook = cook; } @Override public void executeCommand() { cook.cookChicken(); } }
//制作米饭的命令 public class CookRiceCommand implements Command { private Cook cook; public CookRiceCommand(Cook cook){ this.cook = cook; } @Override public void executeCommand() { cook.cookRice(); } }
//服务员类 public class Waiter { //订单 List<Command> commandList = new ArrayList<>(); //添加订单 public void setOrder(Command command){ commandList.add(command); } //取消订单 public void cancelOrder(Command command){ commandList.remove(command); } //通知厨师 public void Notify(){ for(Command command:commandList){ command.executeCommand(); } } }
测试类
public class Test { public static void main(String[] args) { Cook cook = new Cook(); CookChickenCommand cookChickenCommand1 = new CookChickenCommand(cook); CookChickenCommand cookChickenCommand2 = new CookChickenCommand(cook); CookRiceCommand cookRiceCommand = new CookRiceCommand(cook); Waiter waiter = new Waiter(); waiter.setOrder(cookChickenCommand1); waiter.setOrder(cookChickenCommand2); waiter.setOrder(cookRiceCommand); waiter.Notify(); } }
测试结果:
制作红烧鸡!
制作红烧鸡!
制作米饭!
可以看到我们首先定义了命令接口,有两个实现方法,通过他们去通知厨师该做什么菜,然后定义了一个服务员,用来整理订单,有订单的添加和取消两个方法,订单完成后,又服务员通知厨师,发出制作的命令。
命令模式的优点:
1.通过服务员的setOrder()和cancelOrder()我们可以很容易实现队请求的发起,撤销。
2.通过服务员的setOrder()和cancelOrder()我们可以很容易的在命令发生变化时记录变化的日志。
3.可以很容易的添加新的命令类型,并且不影响其他的类。