引言
在软件开发过程中,经常会遇到需要对请求进行一系列处理的情况。例如,在Web应用中,用户的请求可能需要经过身份验证、权限检查、数据校验等步骤。为了使代码结构清晰、降低耦合度、提高可扩展性,可以使用责任链模式来解决此类问题。
责任链模式定义
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它通过将多个处理者(Handler)按照顺序组成一条链,当有请求发生时,沿着这条链依次传递,直到有处理者处理它或处理链结束。该模式使请求的发送者和接收者解耦,客户端无需知道是哪一个处理者最终处理了请求,增强了系统的灵活性。
比如在一个采购系统中,用户需要进行采购下单,对采购的商品会进行很多校验,比如用户是否符合采购用户标准,用户采购的订单库存是否充足,用户需要送达的地址是否可以送到等等一系列校验。按照需求快速开发我们就会在一个校验的方法里面,判断上述一系列条件是否满足,满足才可以生成订单。后面系统进行二次迭代,vip 用户不需要下单,也不需要进行地址校验,这时候可能会加入一个if vip user
的判断 然后再决定是否执行校验,这样简单一次代码结果还好,但是随着系统的不断迭代,特定场景的订单越来越多,判断条件也越加越多,于是乎代码结果就变得难以阅读和维护。
参考Servlet 的Filter + FilterChain, 可以构建一个订单创建的职责链路,根据业务类型来指定对应的职责链路。
Servlet 里面的Filter 和FilterChain 使用的就是责任链模式。每一个职责可以组装,比如filterchain 也有不同的实现
- Filter 接口 -> 实现处理过程
- FilterChain 接口 -> 定义调用链路 责任链模式建议你将这些处理者连成一条链。 链上的每个处理者都有一个成员变量来保存对于下一处理者的引用。 除了处理请求外, 处理者还负责沿着链传递请求。 请求会在链上移动, 直至所有处理者都有机会对其进行处理。
写点代码
以订单创建为例子,会对订单的信息校验,然后再进行创建,如果不满足条件则退出,每种特定的行为的处理都会影响订单创建的结果。
快速开发if-else 一把锁
java
public class OrderService {
void creteOrder() {
OrderBO orderBO = new OrderBO();
if (checkState(orderBO)) {
//do something
}
if(checkAddress(orderBO)) {
//do something
}
if (checkXXX(orderBO)) {
}
//create order
}
private boolean checkXXX(OrderBO orderBO) {
return false;
}
private boolean checkAddress(OrderBO orderBO) {
return false;
}
private boolean checkState(OrderBO orderBO) {
return false;
}
}
使用责任链模式拆分业务逻辑
-
OrderBO ,订单业务对象
-
OrderFilter ,订单处理过滤器接口
-
OrderAddressFilter 实现 OrderFilter
-
OrderStateFilter 实现OrderFilter
-
OrderFilterChain构建订单过滤链路,
- 包含doFilter 和addFilter 方法,维护一个过滤器链表
-
OrderFilterTest指定需要的链路,然后执行过滤。具体代码如下所示
java
//订单创建过滤器
public interface OrderFilter {
void doFilter(OrderBO order, OrderFilterChain chain);
}
java
//地址校验过滤器
@Slf4j
@Component(OrderFilterConstant.ADDRESS)
public class OrderAddressFilter implements OrderFilter {
@Override
public void doFilter(OrderBO order, OrderFilterChain orderFilterChain) {
log.info("执行地址过滤");
orderFilterChain.doFilter(order);
}
}
less
//订单状态校验过滤器
@Component(OrderFilterConstant.State)
@Slf4j
public class OrderStateFilter implements OrderFilter {
@Override
public void doFilter(OrderBO order, OrderFilterChain orderFilterChain) {
log.info("执行订单状态过滤");
orderFilterChain.doFilter(order);
}
}
订单创建责任链
java
@Slf4j
@Component
public class OrderFilterChain {
private int size;
private int position = 0;
private OrderFilter[] orderFilters = new OrderFilter[10];
public void doFilter(final OrderBO order) {
//必须加判断,否则链式调用会死循环,直到StackOverflow
if (this.position < this.size) {
OrderFilter orderFilter = orderFilters[position++];
orderFilter.doFilter(order, this);
}
}
public void addFilter(OrderFilter orderFilter) {
if (orderFilters.length == size) {
OrderFilter[] newOrderFilters = new OrderFilter[size + 10];
System.arraycopy(orderFilters, 0, newOrderFilters, 0, size);
orderFilters = newOrderFilters;
}
orderFilters[size++] = orderFilter;
}
}
客户端测试代码
java
@SpringBootTest
public class OrderFilterTest {
@Autowired
private OrderFilterChain orderFilterChain;
@Autowired
private Map<String, OrderFilter> orderFilterMap;
@Autowired
private List<OrderFilter> orderFilters;
@Test
public void test() {
for (OrderFilter orderFilter : orderFilters) {
orderFilterChain.addFilter(orderFilter);
}
// orderFilterChain.addFilter(orderFilterMap.get(OrderFilterConstant.ADDRESS));
// orderFilterChain.addFilter(orderFilterMap.get(OrderFilterConstant.State));
orderFilterChain.doFilter(null);
}
}
如果想要指定新的责任链,比如A业务不需要进行某个校验,那么在client 调用的时候,就不要添加到filterChain 即可
总结
在上面的案例中,我们把订单创建的每一个职责抽取成了单独的Filter ,每一个filter 可以通过FilterChain 进行链式调用。如果后续有新的责任链路的时候,可以在调用方指定校验链路的顺序和类型,实现对应的业务逻辑处理。
在使用责任链模式之后,后续迭代时既不需要修改原有的代码,也可以重新编排新的FilterChain。