写点什么

设计模式的故事之三:责任链模式

作者:Java你猿哥
  • 2023-04-26
    湖南
  • 本文字数:2259 字

    阅读完需:约 7 分钟

故事

在一个偏远的小镇上,有一个叫做“责任链咖啡馆”的地方。这个咖啡馆有着独特的经营理念,即通过使用责任链模式来处理客户的订单。

这个咖啡馆的负责人是一位名叫 Jack 的人,他非常喜欢 Java 设计模式,并且在经营咖啡馆的时候也喜欢运用这些模式。因此,他决定在咖啡馆的运营中使用责任链模式。

在这个咖啡馆中,每个订单都会通过一个处理链来进行处理。这个处理链包含了多个处理节点,每个节点都有自己的处理逻辑。当一个订单到达咖啡馆时,会从链的头部开始处理,直到最后一个节点结束,完成整个订单的处理。

举个例子,比如有一个客人点了一杯咖啡和一块蛋糕。这个订单会首先进入到咖啡处理节点中,进行咖啡的制作。制作完成后,订单会继续流转到下一个节点,即蛋糕处理节点中,进行蛋糕的制作。最后,订单会进入到结算节点中,完成订单的结算。

这个处理链的好处在于,每个节点只需要关注自己的处理逻辑,而不需要关心整个订单的处理过程。这样可以提高代码的可读性和可维护性,并且也方便对处理链进行扩展和修改。

故事讲完了,接下来讲知识点

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

  1. 抽象处理者(Handler):定义了一个处理请求的接口,并且包含了一个指向下一个处理者的引用。

  2. 具体处理者(ConcreteHandler):实现了抽象处理者的接口,并且处理它所负责的请求。如果该处理者无法处理请求,那么它会将请求传递给下一个处理者。

  3. 客户端(Client):创建了一个责任链,并且向该链中的第一个处理者发出请求。


责任链模式通常用于以下场景:

  1. 处理复杂的请求:当一个请求需要被多个对象处理时,可以使用责任链模式来分解该请求,并且使得每个对象都只需要关注自己的处理部分。

  2. 避免请求发送者和接收者之间的耦合关系:通过将请求的发送者和接收者解耦,可以使得系统更加灵活,并且易于维护。

  3. 可以动态地增加或删除处理者:由于责任链中的对象是动态添加或删除的,因此可以根据需要进行动态调整。

示例

为了更好地理解责任链模式,我们可以看一个简单的示例。

假设我们正在开发一个客户服务系统,该系统中需要对客户的投诉进行处理。投诉可以被分为三种类型:一般投诉、严重投诉和紧急投诉。每个投诉都需要被处理,并且需要根据投诉的类型来决定如何处理。如果一个处理者无法处理某个投诉,那么该投诉将被传递给下一个处理者,直到被处理为止。

我们可以使用责任链模式来实现这个功能。首先,我们需要定义一个抽象处理者类,该类包含一个指向下一个处理者的引用和一个处理请求的方法。

public abstract class ComplaintHandler {    protected ComplaintHandler successor;
public void setSuccessor(ComplaintHandler successor) { this.successor = successor;}
public abstract void handleComplaint(Complaint complaint);}
复制代码

然后,我们可以定义三个具体处理者类,分别用于处理一般投诉、严重投诉和紧急投诉。这三个处理者类都继承自抽象处理者类,并且实现了处理请求的方法。

public class GeneralComplaintHandler extends ComplaintHandler {    @Override    public void handleComplaint(Complaint complaint) {        if (complaint.getType() == ComplaintType.GENERAL) {            System.out.println("一般投诉已经被处理。");        } else {            successor.handleComplaint(complaint);        }    }}
public class SeriousComplaintHandler extends ComplaintHandler { @Override public void handleComplaint(Complaint complaint) { if (complaint.getType() == ComplaintType.SERIOUS) { System.out.println("严重投诉已经被处理。"); } else { successor.handleComplaint(complaint); } }}
public class EmergencyComplaintHandler extends ComplaintHandler { @Override public void handleComplaint(Complaint complaint) { if (complaint.getType() == ComplaintType.EMERGENCY) { System.out.println("紧急投诉已经被处理。"); } else { System.out.println("无法处理该投诉。"); } }}
复制代码

最后,我们可以创建一个责任链,并且向该链中的第一个处理者发出请求。

public class ComplaintService {    private ComplaintHandler complaintHandler;
public ComplaintService() { complaintHandler = new GeneralComplaintHandler(); ComplaintHandler seriousHandler = new SeriousComplaintHandler(); ComplaintHandler emergencyHandler = new EmergencyComplaintHandler();
complaintHandler.setSuccessor(seriousHandler); seriousHandler.setSuccessor(emergencyHandler); }
public void handleComplaint(Complaint complaint) { complaintHandler.handleComplaint(complaint); }}
复制代码

使用上述代码,我们就可以根据投诉的类型来决定如何处理该投诉,并且可以动态添加或删除处理者。

Spring 中的应用

Spring 框架中也使用了责任链模式,其中最常见的应用是拦截器(Interceptor)。拦截器是一种在请求处理过程中,可以拦截请求并进行处理的组件。在 Spring 框架中,拦截器通常用于实现 AOP(面向切面编程)功能。

拦截器通常是以责任链的形式存在的。在 Spring 框架中,每个拦截器都继承自 HandlerInterceptor 接口,并且包含了三个方法:preHandle、postHandle 和 afterCompletion。这三个方法分别在请求处理前、请求处理后和请求处理完成后调用。

用户头像

Java你猿哥

关注

一只在编程路上渐行渐远的程序猿 2023-03-09 加入

关注我,了解更多Java、架构、Spring等知识

评论

发布
暂无评论
设计模式的故事之三:责任链模式_Java_Java你猿哥_InfoQ写作社区