设计模式速记-命令模式
命令模式
命令模式定义:
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
程序中经常需要把处理逻辑封装为一个处理方法,使用该逻辑时只需要调用方调用此方法即可,所以方法的调用者和方法的实现者有紧密的耦合关系,如果在“调用方-实现方”之间使用命令模式,耦合关系就会减弱
比如餐馆点餐系统,服务员将客户提交的菜品订单交给厨师,那么订单就相当于命令,服务员等价于调用者,厨师相当于执行者。(示例代码在后文)
命令模式的优缺点
优点
- 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
- 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
- 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
- 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。
缺点
- 可能产生大量具体命令类。因为计对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。
构成角色
- 抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。
- 具体命令角色(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
- 实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
- 调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
示例
1. 场景描述
使用命令模式实现餐馆点餐系统,服务员将客户提交的菜品订单交给厨师,其中订单、服务员、厨师分别等价于命令、调用者、实现者。
2. 实现代码
-
抽象命令角色
/** * @Description 抽象命令角色 */ public interface Instruct { /** * 提交菜单(命令)给厨师(执行者) */ void submit(); }
-
具体命令角色
/** * @Description 菜单,相当于具体命令角色 */ public class Menu implements Instruct{ private List<String> orderList; private int tableNum; private Chef chef; public Menu(int tableNum ,List<String> orderList){ this.tableNum = tableNum; this.orderList = orderList; this.chef = new Chef(); } @Override public void submit() { this.chef.cooking(this.tableNum,this.orderList); } }
-
实现者
/** * @Description 服务员,调用者 */ public class Waiter { private Menu menu; public Waiter(Menu menu){ this.menu = menu; } public void setMenu(Menu menu){ this.menu = menu; } public void submitList(){ menu.submit(); } }
-
调用者
/** * @Description 厨师,相当于接受者 */ public class Chef { public void cooking(int tableNum , List<String> orderList){ System.out.println(String.format("桌号:%s 正在准备,菜单列表:%s",tableNum,orderList)); } }
-
测试代码
public void customerTest(){ Menu menu1 = new Menu(1, Lists.newArrayList("鱼","骨头","面包")); Menu menu2 = new Menu(2, Lists.newArrayList("沙拉","肉汤","面条")); Waiter waiter = new Waiter(menu1); waiter.submitList(); waiter.setMenu(menu2); waiter.submitList(); }
-
测试结果
桌号:1 正在准备,菜单列表:[鱼, 骨头, 面包] 桌号:2 正在准备,菜单列表:[沙拉, 肉汤, 面条]