笔记 笔记
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

EasT-Duan

Java 开发
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

购买兑换码请添加

添加时候请写好备注,否则无法通过。

  • 设计模式

    • 简介

    • 原则

    • UML

    • 创建型

    • 结构型

    • 行为型

      • 模板模式
      • 命令模式
      • 访问者模式
      • 迭代器模式
      • 中介者模式
      • 备忘录模式
      • 解释器模式
      • 状态模式
      • 策略模式
      • 职责链模式
        • 简介
        • 代码示例
        • 说明
        • 职责链模式在 SpringMVC 框架应用
  • JVM 详解

  • Linux

  • Redis

  • 分布式锁

  • Shiro

  • Gradle

  • Java 进阶
  • 设计模式
  • 行为型
EasT-Duan
2023-12-05
目录

职责链模式

欢迎来到我的 ChatGPT 中转站,极具性价比,为付费不方便的朋友提供便利,有需求的可以添加左侧 QQ 二维码,另外,邀请新用户能获取余额哦!最后说一句,那啥:请自觉遵守《生成式人工智能服务管理暂行办法》。

# 简介

职责链模式(Chain of Responsibility Pattern),又叫责任链模式,为请求创建了一个接收者对象的链。这种模式对请求的发送者和接收者进行解耦。

职责链模式通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求, 那么它会把相同的请求传给下一个接收者,依此类推。

  • Handler:抽象的处理者,定义了一个处理请求的接口,同时包含另外 Handler。
  • ConcreteHandler1 和 2:是具体的处理者,处理它自己负责的请求,可以访问它的后继者(setSuccessor),如果可以处理当前请求,则处理(handleRequest),否则就将该请求交个后继者去处理,从而形成一个职责链。
  • Request:表示一个请求.

# 代码示例

编写程序完成学校 OA 系统的采购审批项目:

  • 采购员采购教学器材
  • 如果金额小于等于 5000,由教学主任审批。
  • 如果金额小于等于 10000,由院长审批。
  • 如果金额小于等于 30000,由副校长审批。
  • 如果金额超过 30000 以上,由校长审批。

/**
 * 定义一个采购请求
 */
@AllArgsConstructor
@Getter
public class PurchaseRequest {

    private double amount; // 请求的金额。
    private String itemName;    //请求购入的器材
}
1
2
3
4
5
6
7
8
9
10
/**
 * 抽象的审批者
 */
public abstract class Approver {
    public Approver(String name) {
        this.name = name;
    }
    protected String name;
    protected Approver next;

    // 设置下一个审批者
    void setNext(Approver approver) {
        this.next = approver;
    }

    abstract void handleRequest(PurchaseRequest request);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * 教学主任
 */
public class TeachingDirector extends Approver {
    public TeachingDirector() {
        super("教学主任");
    }

    @Override
    void handleRequest(PurchaseRequest request) {
        if (request.getAmount() <= 5000) {
            System.out.println("Purchase request for " + request.getItemName() + " approved by " + name + " apply for " + request.getAmount());
        } else if (next != null) {
            next.handleRequest(request);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * 院长
 */
public class Dean extends Approver {
    public Dean() {
        super("院长");
    }

    @Override
    void handleRequest(PurchaseRequest request) {
        if (request.getAmount() <= 10000) {
            System.out.println("Purchase request for " + request.getItemName() + " approved by " + name + " apply for " + request.getAmount());
        } else if (next != null) {
            next.handleRequest(request);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * 副校长
 */
public class ViceChancellor extends Approver {
    public ViceChancellor() {
        super("副校长");
    }

    @Override
    void handleRequest(PurchaseRequest request) {
        if (request.getAmount() <= 30000) {
            System.out.println("Purchase request for " + request.getItemName() + " approved by " + name + " apply for " + request.getAmount());
        } else if (next != null) {
            next.handleRequest(request);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * 校长
 */
public class Chancellor extends Approver {
    public Chancellor() {
        super("校长");
    }

    @Override
    void handleRequest(PurchaseRequest request) {
        System.out.println("Purchase request for " + request.getItemName() + " approved by " + name + " apply for " + request.getAmount());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * 测试
 */
public class Client {
    public static void main(String[] args) {
        Approver teachingDirector = new TeachingDirector();
        Approver dean = new Dean();
        Approver viceChancellor = new ViceChancellor();
        Approver chancellor = new Chancellor();

        teachingDirector.setNext(dean);
        dean.setNext(viceChancellor);
        viceChancellor.setNext(chancellor);

        teachingDirector.handleRequest(new PurchaseRequest(3000, "Projector"));
        teachingDirector.handleRequest(new PurchaseRequest(8000, "Laptop"));
        teachingDirector.handleRequest(new PurchaseRequest(15000, "Lab Equipment"));
        teachingDirector.handleRequest(new PurchaseRequest(40000, "Server"));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 说明

职责链将请求和处理分开,实现解耦,提高系统的灵活性。

简化了对象,使对象不需要知道链的结构。

性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在 Handler 中设置一个最大节点数量,在 setNext () 方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地破坏系统性能。

调试不方便。采用了类似递归的方式,调试时逻辑可能比较复杂。

最佳应用场景:有多个对象可以处理同一个请求时,比如:多级请求、请假 / 加薪 等审批流程、Java Web 中 Tomcat 对 Encoding 的处理、拦截器等等。

# 职责链模式在 SpringMVC 框架应用

在 DispatcherServlet 类中的 doDispatch () 方法中

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    //...................
    		// 执行前置拦截方法
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            // Actually invoke the handler.
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }

            applyDefaultViewName(processedRequest, mv);
            mappedHandler.applyPostHandle(processedRequest, response, mv);
     //...................
}

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
    for (int i = 0; i < this.interceptorList.size(); i++) {
        HandlerInterceptor interceptor = this.interceptorList.get(i);
        if (!interceptor.preHandle(request, response, this.handler)) {
            triggerAfterCompletion(request, response, null);
            return false;
        }
        this.interceptorIndex = i;
    }
    return true;
}

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
    for (int i = this.interceptorIndex; i >= 0; i--) {
        HandlerInterceptor interceptor = this.interceptorList.get(i);
        try {
            // 在前置拦截方法执行成功后执行,就和上面手写的setNext一样
            interceptor.afterCompletion(request, response, this.handler, ex);
        }
        catch (Throwable ex2) {
            logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#设计模式
上次更新: 2025/04/12, 05:37:39
策略模式
JVM 与 Java 体系结构

← 策略模式 JVM 与 Java 体系结构→

最近更新
01
Reactor 核心
02-24
02
前置条件
10-30
03
计算机网络
09-13
更多文章>
Theme by Vdoing | Copyright © 2019-2025 powered by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式