设计模式之不一样的责任链模式

这篇具有很好参考价值的文章主要介绍了设计模式之不一样的责任链模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它通过将请求的发送者和接收者解耦,使多个对象都有机会处理请求。在这个模式中,请求沿着一个处理链依次传递,直到有一个对象能够处理它为止。

本文将详细介绍责任链模式的概述、应用场景以及代码示例,来帮助读者更好地理解和应用这个模式。

1. 简介

模式概述

责任链模式的核心思想是将请求的发送者和接收者解耦,使得多个对象都有机会处理请求。在责任链模式中,请求会沿着一个处理链依次传递,每个处理者都有机会处理请求,如果一个处理者不能处理请求,则将请求传递给下一个处理者,直到有一个处理者能够处理它。

责任链模式包含以下几个角色:

  • 抽象处理者(Handler):定义了处理请求的接口,通常包含一个指向下一个处理者的引用,用于将请求传递给下一个处理者。
  • 具体处理者(ConcreteHandler):实现了处理请求的接口,具体处理者可以决定是否处理请求,如果不能处理,则将请求传递给下一个处理者。
  • 客户端(Client):创建处理者对象并组成责任链的结构,负责将请求发送给第一个处理者。

优点与缺点

优点:

  • 责任链模式可以实现请求的发送者和接收者之间的解耦。发送者只需要将请求发送给第一个处理者,无需关心具体是哪个处理者来处理。这样,系统的灵活性大大增强,可以随时增加或修改处理者的顺序。
  • 责任链模式能够避免请求的发送者和接收者之间的紧耦合。每个处理者只需要关心自己负责的请求类型,无需关心其他请求。这样,系统的可维护性也得到了提升。
  • 责任链模式可以灵活地动态添加或删除处理者。我们可以根据实际情况来调整责任链的结构,以满足不同的业务需求。

缺点:

  • 复杂度会明显提升,如果责任链过长或者处理者之间的关系复杂,可能还会导致性能下降和调试困难。

应用场景

责任链模式在许多不同的应用场景中都有广泛的应用。下面列举了一些常见的应用场景:

  • 请求处理链:当一个请求需要经过多个处理步骤或处理者进行处理时,可以使用责任链模式。每个处理者负责一部分逻辑,处理完后可以选择将请求传递给下一个处理者,从而形成一个处理链。
  • 日志记录:在日志系统中,可以使用责任链模式来记录日志。不同的处理者可以负责不同级别的日志记录,例如,一个处理者负责记录错误日志,另一个处理者负责记录调试日志,然后按照链式结构传递日志。
  • 身份验证和权限检查:在身份验证和权限检查系统中,可以使用责任链模式来验证用户的身份和权限。每个处理者可以检查特定的条件,例如用户名和密码的正确性、账户是否锁定等。如果一个处理者无法通过验证,可以将请求传递给下一个处理者。
  • 数据过滤和转换:在数据处理过程中,可以使用责任链模式来进行数据过滤和转换。每个处理者可以根据特定的条件过滤数据或对数据进行转换,然后将处理后的数据传递给下一个处理者。
  • 错误处理和异常处理:在错误处理和异常处理系统中,可以使用责任链模式来处理错误和异常。不同的处理者可以处理不同类型的错误或异常,并根据需要将错误或异常传递给下一个处理者进行进一步处理或记录。

2. Java 代码示例

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 框架实现一个高级版的责任链模式。

3. Spring 代码示例

在实际开发中,一个请求会在多个处理器之间流转,每个处理器都可以处理请求。

假设我们有一个 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);
}

-------------------------------------------
订单参数检验通过
支付宝预下单成功

4. 总结

总的来说,责任链模式适用于存在多个处理步骤、每个处理步骤具有独立逻辑或条件、需要灵活组合和扩展的场景。通过责任链模式,可以将复杂的处理逻辑拆分为多个独立的处理步骤,并且可以动态地组合和调整处理步骤的顺序,从而提高系统的灵活性和可维护性。希望本文能够帮助读者理解和应用责任链模式,提升软件设计和开发的能力。

关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力!文章来源地址https://www.toymoban.com/news/detail-471184.html

到了这里,关于设计模式之不一样的责任链模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【设计模式-05】Facade门面Mediator调停者 | Decorator装饰器 | Chain Of Responsibility责任链

    一般是系统内部相互交错,比如 消息中间件(MQ) 就是这种设计模式,对各个功能或系统之间进行解耦。 业务场景:论坛或者博客发表帖子或者评论,对敏感词过滤处理。使用责任链的模式进行过滤处理。 把变化的进行封装处理 核心代码实现 GitHub - jxaufang168/Design-Patterns: 设计

    2024年01月19日
    浏览(94)
  • 设计模式-责任链模式

    遇到一个面试的场景题目,让实现税率的计算 请使用Java语言实现如下税率计算: 1~5000 税率 0 5001~8000 3% 8001~17000 10% 17001~30000 20% 30001~40000 25% 40001~60000 30% 60001~85000 35% 85001~ 45% 要求 ⅰ. 逻辑正确,代码优雅 ⅱ. 可扩展性,考虑区间的变化,比如说起征点从5000变成10000等等,或者

    2024年02月11日
    浏览(25)
  • 【设计模式】责任链模式

    顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。 在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处

    2024年02月12日
    浏览(31)
  • 设计模式:责任链模式

    责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象按照顺序处理请求,直到其中一个对象能够处理该请求为止。责任链模式将请求发送者和接收者解耦,使得多个对象都有机会处理请求,同时避免了请求发送者与接收者之间的直接耦合关系。 在

    2024年02月07日
    浏览(37)
  • 设计模式——责任链模式

    使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,知道有对象处理它为止。 优点 能将请求和处理分开。请求者可以不用知道是谁处理的,处理者可以不用知道请求的全貌,两者解耦提高系

    2024年02月15日
    浏览(33)
  • 《设计模式》责任链模式

    定义 : 责任链模式将链中每一个节点都看成一个对象,并且将这些节点对象连成一条链,请求会沿着这条链进行传递,直到有对象处理它为止,这使得多个对象都有机会接收请求,避免了请求发送者和接收者之间的耦合。 属于 行为型 设计模式。 责任链模式的角色组成 :

    2024年02月13日
    浏览(36)
  • 设计模式—责任链模式

    一、待解决问题 : 减少代码中 if else 语句,降低代码圈复杂度或深度,增强可读性。 1、需求背景: 采购订单创建,需要验证采购员、物料、供应商、供应商的银行账号等信息。如采购员权限到期、或供应商失效等问题,都无法下单。 2、代码如下: 学习使用责任链模式后

    2024年02月10日
    浏览(32)
  • 面试设计模式-责任链模式

    在进行请假申请,财务报销申请,需要走部门领导审批,技术总监审批,大领导审批等判断环节。存在请求方和接收方耦合性太强,代码会比较臃肿,不利于扩展和维护。 针对上面,使用责任链模式,将请求方和接收方的业务进行解耦, 客户端发送一个请求,由一个抽象的

    2024年02月09日
    浏览(30)
  • 设计模式详解-责任链模式

    类型:行为型模式 实现原理:为请求创建了一个接收者对象的链。对请求的发送者和接收者进行解耦,每个接收者都包含对另一个接收者的引用,如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。 作用:避免请求发送者与接收者耦合在一

    2024年02月12日
    浏览(29)
  • 重温设计模式 --- 责任链模式

    责任链模式 是一种行为型设计模式,它通过一条由多个处理器组成的链来处理请求,每个处理器都有机会处理请求,如果一个处理器不能处理该请求,它会将请求传递给下一个处理器,直到请求被处理为止。 在实际应用中,责任链模式常用于处理请求的分发、事件处理等场

    2024年02月13日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包