目录
1、简介
1.1、定义
命令模式:将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。(同时也支持可撤销的操作)
1.2、解决的问题
通常在系统设计中,行为请求者和行为实现者是紧耦合的关系。而在一些特定的场景下,比如:需要对行为进行记录、撤销或重做、事务等处理时,需要将行为请求者和行为实现者分离开来,这时就可以用到命令模式。
1.3、模式结构
- Command:定义命令的接口,声明执行的方法
- ConcreteCommand:命令接口实现对象,是“命令接口”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作
- Receiver:接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能
- Invoker:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口
- Client:创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行
1.4、结构类图
1.5、运作流程
- Client创建一个ConcreteCommand对象并指定他的Receiver对象
- 某个Invoker对象存储该ConcreteCommand对象
- 该Invoker通过调用Command对象的Execute操作来提交一个请求。若该命令是可撤销的,ConcreteCommand就在执行Execute操作之前存储当前状态以用于取消该命令
- ConcreteCommand对象对调用它的Receiver的一些操作以执行该请求
2、示例Demo
2.1、Command
package com.jbp.designpattern.command;
/**
* @ClassName: Order
* @description: 命令接口 --- Command
* @author: JiangBeiPing
* @create: 2021-07-23 11:15
* @Version: 1.0
**/
public interface Order {
void execute();
}
2.2、ConcreteCommand
package com.jbp.designpattern.command;
/**
* @ClassName: BuyStock
* @description: 加库存 --- ConcreteCommmand
* @author: JiangBeiPing
* @create: 2021-07-23 11:39
* @Version: 1.0
**/
public class BuyStock implements Order{
private Stock stock;
public BuyStock(Stock stock) {
this.stock = stock;
}
@Override
public void execute() {
stock.buy();
}
}
package com.jbp.designpattern.command;
/**
* @ClassName: SellStock
* @description: 清库存 --- ConcreteCommmand
* @author: JiangBeiPing
* @create: 2021-07-23 11:41
* @Version: 1.0
**/
public class SellStock implements Order{
private Stock stock;
public SellStock(Stock stock) {
this.stock = stock;
}
@Override
public void execute() {
stock.sell();
}
}
2.3、Receiver
package com.jbp.designpattern.command;
/**
* @ClassName: Stock
* @description: 请求类 --- Receiver
* @author: JiangBeiPing
* @create: 2021-07-23 11:16
* @Version: 1.0
**/
public class Stock {
private String name = "库存一号";
// 数量
private int quantity = 10;
public void buy(){
System.out.println("名字:" + name + ",数量:" + quantity);
}
public void sell(){
System.out.println("名字:" + name + ",数量:" + quantity);
}
}
2.4、Invoker
package com.jbp.designpattern.command;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: Broker
* @description: 命令调用类 --- invoker
* @author: JiangBeiPing
* @create: 2021-07-23 11:43
* @Version: 1.0
**/
public class Broker {
private List<Order> orderList = new ArrayList<>();
// 加库存
public void takeOrder(Order order){
orderList.add(order);
}
// 清库存
public void placeOrders(){
for (Order order : orderList) {
order.execute();
}
orderList.clear();
}
}
2.5、Client
package com.jbp.designpattern.command;
/**
* @ClassName: test
* @description: 测试 --- Client
* @author: JiangBeiPing
* @create: 2021-07-23 11:50
* @Version: 1.0
**/
public class test {
public static void main(String[] args) {
Stock stock = new Stock();
BuyStock buyStock = new BuyStock(stock);
SellStock sellStock = new SellStock(stock);
Broker broker = new Broker();
broker.takeOrder(buyStock);
broker.takeOrder(sellStock);
broker.placeOrders();
}
}
3、优缺点
3.1、优点
- 类间解耦:调用者角色与接收者角色之间没有任何依赖关系
- 可扩展性:Command的子类具备高扩展性
- 可以比较容易地设计一个组合命令
3.2、缺点
- Command的子类过多(如果有过多的命令,就会有过多的Command子类)
3.3、使用场景
- 队列请求
- 日志请求
- 系统需要将一组操作组合在一起,即支持宏命令