1、概念
命令模式是为了将请求发起者和请求处理者解耦,从而提高请求的处理效率。
请求发起者和请求处理者有许多同义词,例如生产者和消费者,client和Server。
命令模式涉及到四个角色,掌握它们之间的关系和职责是掌握命令模式的核心。
- Client:请求发起者。
- Command:它代表请求的类型。
- Invoker:它代表请求的协调者。
- Receiver:请求处理者。
为了更方便的理解命令模式,结合生活中的点餐场景。当我们进入餐馆点餐时,
- 顾客就是请求发起者,他点了一种食物。
- 菜单就是请求类型列表,顾客点的食物对应具体的请求类型。
- 服务员将我们的食物告知厨师,服务员扮演着Invoker的角色。
- 厨师为我们做饭,他扮演着请求处理者的角色。
2、UML图
3、代码
ICommand代表请求的类型,它的实现类与Receiver的关系为组合关系。
/** * * @Title: ICommand.java * @Package command * @Description: 扮演着点餐场景中菜单的角色,在命令模式代表请求的类型 * @version V1.0 */ public interface ICommand { void doSomething(); }
CommandTypeA,代表一种具体的请求类型。
/** * * @Title: CommandTypeA.java * @Package command * @Description: 代表一种具体的请求类型,这里抽象为TypeA * @version V1.0 */ public class CommandTypeA implements ICommand { // 组合关系,它是必备的属性 private Receiver receiver; public CommandTypeA(Receiver receiver) { this.receiver = receiver; } @Override public void doSomething() { receiver.dealTypeA(); } }
Invoker,扮演着协调者的角色,主要是将Command传递给请求处理者。
/** * * @Title: Invoker.java * @Package command * @Description: 在点餐场景中扮演着服务员的角色,在命令模式中扮演着协调者的角色 * @version V1.0 */ public class Invoker { public void invoke(ICommand command) { command.doSomething(); } }
Receiver,它代表着请求处理者的角色。
/** * * @Title: Receiver.java * @Package command * @Description: 扮演着请求处理者的角色,在点餐场景中扮演着厨师的角色 * @version V1.0 */ public class Receiver { public void dealTypeA() { System.out.println("正在处理A类型的请求"); } }
Client,它扮演着请求发起者的角色。
/** * * @Title: Client.java * @Package command * @Description: 扮演着请求发起者的角色,在点餐模型中扮演着顾客的角色 * @version V1.0 */ public class Client { public static void main(String[] args) { // 创建请求处理者,厨师 Receiver receiver = new Receiver(); // 创建具体的请求类型 ICommand command = new CommandTypeA(receiver); // 创建协调者,服务员 Invoker invoker = new Invoker(); // 处理真正的请求 invoker.invoke(command); } }
4、代码
在使用命令模式时,需要注意:
请求类型CommandTypeA与Receiver是组合关系,只能通过构造器方式注入依赖。
命令模式本质是为了将请求者和处理者解耦,所以大部分情况下请求都是异步方式进行的,有的可以添加请求队列,设置优先级等等,所以对于某些实时性的请求并不适合。
5、示例
生产者与消费者模型。