责任链模式就是建立多个处理请求的对象,这些对象按照某种顺序组成一条链,(就像链表同样,有个指针能够找到后继)前一个对象保存了下一个对象的实例引用,能够找到下一个对象,请求从头部开始,在这条链上传递,谁能处理就当即处理,请求结束,直到链的结尾。 就像公司审批请假同样,有时候须要部门主管审批完就能够,有时候还须要hr审批经过才行。好比struct框架中的过滤器,也是责任链模式的应用。
ERP系统中不一样优先级的订单处理就能够用责任链模式。例如订单分为预售提早单,普通订单以及紧急发货的订单,建立不一样的处理器进行不一样类型订单的处理,而后按照优先级将这些处理器组成责任链,全部订单都通过这条责任链,根据订单等级的不一样,只有对应等级的处理器才能处理对应等级的订单,这就跟有没有权限是一个道理。spring
责任链模式涉及两个角色:
抽象处理器角色(Handler):持有下一个处理器的对象引用,定义了处理请求的接口,提供了设置下一个处理器的方法。
具体处理器角色(ConcreteHandler):实现或者继承抽象处理器角色。bash
按照如上所说,对三种优先级不一样订单的处理,咱们至少须要定义一个抽象处理器,而后定义三个具体处理器,将这三个处理器按优先级组成责任链,而后在业务逻辑中,将订单交给责任链处理。框架
/**
* 抽象处理器角色
*/
public abstract class Handler {
private Handler nextHandler;
private Integer priority;
public Handler(Integer priority) {
this.priority = priority;
}
public void setHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
/**
* 处理订单请求的传递,若是是当前级别则调用solveOrder()方法处理,不然传递给上一级处理。
* @param order
*/
public final void handleOrder(Order order) {
if (order == null || order.getOrderId() == null) {
throw new RuntimeException("订单信息为空,没法处理");
}
if (order.getPriority() == null) {
throw new IllegalArgumentException("订单"+order.getOrderId()+"没有设置处理级别");
}
if (order.getPriority().equals(this.priority)) {
this.solveOrder(order);
} else {
if (this.nextHandler != null) {
System.out.println(this.getClass().getName()+"没法处理订单"+order.getOrderId()+",传递给高一级的handler处理");
nextHandler.handleOrder(order);
} else {
throw new RuntimeException("没有Handler可以处理当前等级的订单");
}
}
}
/**
* 定义处理订单的方法,由子类实现,处理不一样等级的订单
*/
public abstract void solveOrder(Order order);
}
复制代码
public class Order {
//订单id
private Long orderId;
//订单优先级
private Integer priority;
public Long getOrderId() {
return orderId;
}
public void setOrderId(Long orderId) {
this.orderId = orderId;
}
public Integer getPriority() {
return priority;
}
public void setPriority(Integer priority) {
this.priority = priority;
}
}
复制代码
假设订单中包含订单id和订单优先级。
在抽象处理器中,咱们定义了下一个处理器nextHandler,并定义set方法进行设置,而后定义了一个处理订单的统一方法,子类调用时都是这个入口,对订单信息进行合法性校验,并判断订单的优先级,当前处理器可否处理,若是没法处理就交给下一个处理器,若是没有下一个处理器就抛出异常。ide
/**
* 定义一个Map容器,保存全部订单处理器
*/
public class OrderHandlerMap {
public static Map<Integer, Handler> map = new HashMap<>();
}
复制代码
/**
* 预售订单的处理器,预售订单的优先级最低
*/
@Component
public class PreSellOrderHandler extends Handler implements InitializingBean{
/**
* 设置可以处理的订单优先级=1
*/
PreSellOrderHandler() {
super(1);
}
@Override
public void solveOrder(Order order) {
System.out.println(this.getClass().getName()+"开始处理订单"+order.getOrderId());
}
@Override
public void afterPropertiesSet() {
OrderHandlerMap.map.put(1,this);
}
}
/**
* 正常订单的处理器,设置优先级为2
*/
@Component
public class NormalOrderHandler extends Handler implements InitializingBean{
/**
* 设置可以处理的订单优先级=2
*/
NormalOrderHandler() {
super(2);
}
@Override
public void solveOrder(Order order) {
System.out.println(this.getClass().getName()+"开始处理订单"+order.getOrderId());
}
@Override
public void afterPropertiesSet() {
OrderHandlerMap.map.put(2, this);
}
}
/**
* 紧急发货订单的处理器,设置优先级最高=3
*/
@Component
public class UrgentOrderHandler extends Handler implements InitializingBean{
/**
* 设置可以处理的订单优先级=3
*/
UrgentOrderHandler() {
super(3);
}
@Override
public void solveOrder(Order order) {
System.out.println(this.getClass().getName()+"开始处理订单"+order.getOrderId());
}
@Override
public void afterPropertiesSet() {
OrderHandlerMap.map.put(3,this);
}
}
复制代码
定义了三个优先级不一样的订单处理器,并在spring容器启动时实例化一个处理器对象放到Map容器中。spring-boot
假设如今来了一个订单,责任链要怎么处理呢?测试
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=Application.class)// 指定spring-boot的启动类
public class OrderHandlerTest1 {
@Test
public void test() {
Map<Integer, Handler> handlerMap = OrderHandlerMap.map;
if (handlerMap.isEmpty()) {
throw new RuntimeException("spring中没有注册任何处理器");
}
//获取最低优先级的处理器
Handler handler = null;
for (Map.Entry<Integer,Handler> entry : handlerMap.entrySet()) {
handler = entry.getValue();
if (handler !=null) {
break;
}
}
//测试预售提早单的责任链处理
Order preSellOrder = new Order();
preSellOrder.setOrderId(123L);
preSellOrder.setPriority(1);
handler.handleOrder(preSellOrder);
//测试正常单的责任链处理
Order normalOrder = new Order();
normalOrder.setOrderId(456L);
normalOrder.setPriority(2);
handler.handleOrder(normalOrder);
//测试紧急发货订单的责任链处理
Order urgentOrder = new Order();
urgentOrder.setOrderId(789L);
urgentOrder.setPriority(3);
handler.handleOrder(urgentOrder);
//测试未知等级的订单可否处理
Order unknownOrder = new Order();
unknownOrder.setOrderId(111L);
unknownOrder.setPriority(9);
handler.handleOrder(unknownOrder);
}
@Before
public void before(){
Map<Integer, Handler> handlerMap = OrderHandlerMap.map;
if (handlerMap.isEmpty()) {
throw new RuntimeException("spring中没有注册任何处理器");
}
//先按照优先级排个序
List<Map.Entry<Integer,Handler>> list = new ArrayList<>(handlerMap.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Integer, Handler>>() {
@Override
public int compare(Map.Entry<Integer, Handler> o1, Map.Entry<Integer, Handler> o2) {
return o1.getKey().compareTo(o2.getKey());
}
});
List<Integer> keys = new ArrayList<>(handlerMap.keySet());
Collections.sort(keys);
//设置处理器的更高一级的处理器,keys已是按照优先级排好序的
for (int i=0; i<keys.size(); i++) {
Integer key = keys.get(i);
Handler handler = handlerMap.get(key);
if (i < keys.size()-1) {
Integer nextKey = keys.get(i + 1);
if (nextKey != null) {
Handler nextHandler = handlerMap.get(nextKey);
handler.setHandler(nextHandler);
}
}
}
}
}
复制代码
咱们在测试以前,先将Map中的处理器组成一个按照优先级排列的处理器责任链,并须要设置当前处理器的下一个处理是谁。而后在测试方法中建立了四种不一样优先级的订单,都交给责任链的第一个处理器进行处理,可是真正可以处理该订单的只有对应等级的处理器。运行结果以下,第一个处理器就能够处理订单123,第二个处理器处理订单456,第三个处理器处理订单789,因为订单111等级未知,没有处理器能够处理,就报错。ui