首页 > 应用开发 > IT综合 > 设计模式之不一样的责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它通过将请求的发送者和接收者解耦,使多个对象都有机会处理请求。在这个模式中,请求沿着一个处理链依次传递,直到有一个对象能够处理它为止。
本文将详细介绍责任链模式的概述、应用场景以及代码示例,来帮助读者更好地理解和应用这个模式。
责任链模式的核心思想是将请求的发送者和接收者解耦,使得多个对象都有机会处理请求。在责任链模式中,请求会沿着一个处理链依次传递,每个处理者都有机会处理请求,如果一个处理者不能处理请求,则将请求传递给下一个处理者,直到有一个处理者能够处理它。
责任链模式包含以下几个角色:
责任链模式类结构
优点:
缺点:
责任链模式在许多不同的应用场景中都有广泛的应用。下面列举了一些常见的应用场景:
在
Java 中实现责任链模式有多种方式,包括基于接口、基于抽象类、基于注解等。下面将详细介绍基于接口的常见实现方式。
基于接口的实现方式是通过定义一个处理请求的接口,每个处理者实现这个接口,并在自己的实现中决定是否处理请求和传递请求给下一个处理者。
首先,我们定义一个处理请求的接口
Handler 以及请求入参
Request:
public
interface
Handler {
void
handleRequest
(Request request);
}
public
class
Request {
private String type;
// 省略getter、setter
}
然后,我们创建3个具体的处理者类实现这个接口,在具体处理者类的实现中,首先判断自己是否能够处理请求,如果能够处理,则进行处理;否则将请求传递给下一个处理者。代码如下:
public
class
ConcreteHandlerA
implements
Handler {
private Handler successor;
public
void
setSuccessor
(Handler successor) {
this.successor = successor;
}
public
void
handleRequest
(Request request) {
if (request.getType().equals(
"A")) {
// 处理请求的逻辑
}
else
if (successor !=
null) {
successor.handleRequest(request);
}
}
}
public
class
ConcreteHandlerB
implements
Handler {
private Handler successor;
public
void
setSuccessor
(Handler successor) {
this.successor = successor;
}
public
void
handleRequest
(Request request) {
if (request.getType().equals(
"B")) {
// 处理请求的逻辑
}
else
if (successor !=
null) {
successor.handleRequest(request);
}
}
}
public
class
ConcreteHandlerC
implements
Handler {
private Handler successor;
public
void
setSuccessor
(Handler successor) {
this.successor = successor;
}
public
void
handleRequest
(Request request) {
if (request.getType().equals(
"C")) {
// 处理请求的逻辑
}
else
if (successor !=
null) {
successor.handleRequest(request);
}
}
}
接下来,我们创建一个客户端类 Client,用于创建处理者对象并组成责任链的结构:
public
class
Client {
public
static
void
main
(String[] args) {
Handler handlerA =
new ConcreteHandlerA();
Handler handlerB =
new ConcreteHandlerB();
Handler handlerC =
new ConcreteHandlerC();
handlerA.setSuccessor(handlerB);
handlerB.setSuccessor(handlerC);
// 创建请求并发送给第一个处理者
Request request =
new Request(
"A");
handlerA.handleRequest(request);
}
}
在客户端类中,我们创建了具体的处理者对象,并通过
setSuccessor() 方法将它们组成一个责任链的结构。然后,创建一个请求对象,并将请求发送给第一个处理者。
基于接口的实现方式简单直观,每个处理者只需要实现一个接口即可。但是它的缺点是如果责任链较长,需要创建多个处理者对象,增加了系统的复杂性和资源消耗。下面基于
Spring 框架实现一个 heigh level 版的责任链模式。
在实际开发中,一个请求会在多个处理器之间流转,每个处理器都可以处理请求。
假设我们有一个 Spring 框架开发的订单处理系统,订单需要依次经过订单检查、库存处理、支付处理。如果某个处理环节无法处理订单,将会终止处理并返回错误信息,只有每个处理器都完成了请求处理,这个订单才算法下单成功。
首先,我们定义一个订单类
Order:
@Data
@AllArgsConstructor
public
class
orderNo {
private String orderNumber;
private String paymentMethod;
private
boolean stockAvailability;
private String shippingAddress;
}
然后,我们定义一个抽象订单处理者类
OrderHandler:
public
abstract
class
OrderHandler {
public
abstract
void
handleOrder
(Order order);
}
接下来,我们创建具体的订单处理者类继承自抽象订单处理者类,实现相应的方法,并注册到
Spring 中,
@Component
public
class
CheckOrderHandler
extends
OrderHandler {
public
void
handleOrder
(Order order) {
if (StringUtils.isBlank(order.getOrderNo())) {
throw
new RuntimeException(
"订单编号不能为空");
}
if (order.getPrice().compareTo(BigDecimal.ONE) <=
0) {
throw
new RuntimeException(
"订单金额不能小于等于0");
}
if (StringUtils.isBlank(order.getShippingAddress())) {
throw
new RuntimeException(
"收货地址不能为空");
}
System.out.println(
"订单参数检验通过");
}
}
@Component
public
class
StockHandler
extends
OrderHandler {
public
void
handleOrder
(Order order) {
if (!order.isStockAvailability()) {
throw
new RuntimeException(
"订单库存不足");
}
System.out.println(
"库存扣减成功");
}
}
@Component
public
class
AliPaymentHandler
extends
OrderHandler {
public
void
handleOrder
(Order order) {
if (!order.getPaymentMethod().equals(
"支付宝")) {
throw
new RuntimeException(
"不支持支付宝以外的支付方式");
}
System.out.println(
"支付宝预下单成功");
}
}
在具体订单处理者类的实现中,
CheckOrderHandler 负责做订单参数检查、
StockHandler 负责做库存扣减、
AliPaymentHandler 负责做预下单,每个处理者的逻辑都是相互独立各不不干扰。
最后,我们创建一个订单生产链条
BuildOrderChain ,用于组成责任链的链条处理结构:
@Component
public
class
BuildOrderChain {
@Autowired
private AliPaymentHandler aliPaymentHandler;
@Autowired
private CheckOrderHandler checkOrderHandler;
@Autowired
private StockHandler stockHandler;
List<OrderHandler> list =
new ArrayList<>();
@PostConstruct
public
void
init
() {
// 1. 检查订单参数
list.add(checkOrderHandler);
// 2. 扣减库存
list.add(stockHandler);
// 3. 支付宝预下单
list.add(aliPaymentHandler);
}
public
void
doFilter
(Order order) {
for (OrderHandler orderHandler :
this.list) {
orderHandler.handleOrder(order);
}
}
}
订单生产链条
BuildOrderChain 类中,我们通过
@PostConstruct 注解下的
init() 初始化方法,将具体的订单处理者按代码顺序组成一个责任链的结构。然后通过
doFilter(order) 方法遍历处理者集合依次处理。
运行代码:
@Slf4j
@SpringBootTest
@RunWith(SpringRunner
.
class)
public
class
OrderChainTest {
@Autowired
private BuildOrderChain buildOrderChain;
@Test
public
void
test
() {
Order order =
new Order(
"123456",
"支付宝",
true,
"长沙",
new BigDecimal(
"100"));
buildOrderChain.doFilter(order);
}
}
-------------------------------
订单参数检验通过
库存扣减成功
支付宝预下单成功
可以看到订单依次经过校验处理器、库存处理器和支付处理器进行处理,直到最后完成整个订单的处理。
在举个例子,假如我们的订单针对的是虚拟不限库存商品,我们不需要进行库存扣减,那我们可以直接新建
VirtualGoodsOrderChain 虚拟商品订单生产链条类,代码如下,
@Component
public
class
VirtualGoodsOrderChain {
@Autowired
private AliPaymentHandler aliPaymentHandler;
@Autowired
private CheckOrderHandler checkOrderHandler;
List<OrderHandler> list =
new ArrayList<>();
@PostConstruct
public
void
init
() {
// 1. 检查订单参数
list.add(checkOrderHandler);
// 2 支付宝预下单
list.add(aliPaymentHandler);
}
public
void
doFilter
(Order order) {
for (OrderHandler orderHandler :
this.list) {
orderHandler.handleOrder(order);
}
}
}
运行代码:
@Test
public
void
virtualOrderTest
() {
Order order =
new Order(
"123456",
"支付宝",
true,
"长沙",
new BigDecimal(
"100"));
virtualGoodsOrderChain.doFilter(order);
}
-------------------------------------------
订单参数检验通过
支付宝预下单成功
总的来说,责任链模式适用于存在多个处理步骤、每个处理步骤具有独立逻辑或条件、需要灵活组合和扩展的场景。通过责任链模式,可以将复杂的处理逻辑拆分为多个独立的处理步骤,并且可以动态地组合和调整处理步骤的顺序,从而提高系统的灵活性和可维护性。希望本文能够帮助读者理解和应用责任链模式,提升软件设计和开发的能力。
关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力!
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70029997/viewspace-2956577/ ,如需转载,请注明出处,否则将追究法律责任。