Java设计模式-责任链模式

责任链模式: 将能够处理某一类请求的对象串成一条链, 请求沿链传递, 链上的对象逐个判断是否有能力处理该请求. 使多个对象都有机会处理请求, 从而避免请求发送者和接收者之间的耦合关系.

(图片来源: 设计模式: 可复用面向对象软件的基础)

优势: 发出请求的客户端并不知道链上的哪个对象最终处理该请求, 这使得系统可以在不影响客户端的前提下动态地重新组织和分配责任.

模式实现

案例: 雇员要求 (请假 & 涨薪), 要经过总监Director -> 经理Manager -> 总经理GeneralManager的层层审批.

Handler:

定义一个处理请求的接口, 内持继任者(可选):

public abstract class Leader {
    protected Leader superior;
    protected String name;
    protected Leader(Leader superior, String name) {
        this.superior = superior;
        this.name = name;
    }
    public abstract void handle(Request request);
}

ConcreteHandler

处理它所负责的请求, 可访问它的后继者;

如果可处理该请求, 处理之, 否则将请求转发:

// 总监
class Director extends Leader {
    public Director(Leader superior, String name) {
        super(superior, name);
    }
    @Override
    public void handle(Request request) {
        if (request.getType().equals("请假") && request.getCount() <= 10) {
            System.out.println("[ " + request.getContent() + "] 请假 [" + request.getCount() + "]天, 总监 [" + name + "] 审批通过");
        } else {
            if (superior != null) {
                superior.handle(request);
            }
        }
    }
}
// 经理
class Manager extends Leader {
    public Manager(Leader superior, String name) {
        super(superior, name);
    }
    @Override
    public void handle(Request request) {
        if (request.getType().equals("请假") && request.getCount() <= 20) {
            System.out.println("[ " + request.getContent() + "] 请假 [" + request.getCount() + "]天, 经理 [" + name + "] 审批通过");
        } else if (request.getType().equals("涨薪") && request.getCount() <= 1000) {
            System.out.println("[ " + request.getContent() + "]  涨薪 [" + request.getCount() + "]RMB, 经理 [" + name + "] 审批通过");
        } else {
            if (superior != null) {
                superior.handle(request);
            }
        }
    }
}
// 总经理
class GeneralManager extends Leader {
    public GeneralManager(Leader superior, String name) {
        super(superior, name);
    }
    @Override
    public void handle(Request request) {
        if (request.getType().equals("请假")) {
            if (request.getCount() <= 30) {
                System.out.println("[ " + request.getContent() + "] 请假 [" + request.getCount() + "]天, 总经理 [" + name + "] 审批通过");
            } else {
                System.out.println("[ " + request.getContent() + "] 你干脆辞职算了");
            }
        } else if (request.getType().equals("涨薪")) {
            if (request.getCount() <= 10_000) {
                System.out.println("[ " + request.getContent() + "]  涨薪 [" + request.getCount() + "]RMB, 总经理 [" + name + "] 审批通过");
            } else {
                System.out.println("你咋不上天呢");
            }
        }
    }
}

Client

向链上的具体处理者对象提交请求:

public class Client {
    @Test
    public void client() {
        Leader generalManger = new GeneralManager(null, "刘备");
        Leader manager = new Manager(generalManger, "诸葛亮");
        Leader director = new Director(manager, "赵云");
        director.handle(new Request("请假", "翡青", 32));
        director.handle(new Request("涨薪", "zjf", 1500));
    }
}
public class Request {
    private String type;
    private String content;
    private int count;
    public Request() {
    }
    public Request(String type, String content, int count) {
        this.type = type;
        this.content = content;
        this.count = count;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
}

注: 非链表实现责任链 - 还可通过集合、数组等形式存储责任链, 很多项目中, 每个具体的Handler并不是开发团队定义的, 而是项目上线后又外部单位追加的, 此时使用链表方式定义chain of responsibility就很困难, 此时可选择使用集合存储.

小结

优缺点

降低耦合度: 客户提交一个请求, 请求沿链传递直至一个ConcreteHandler最终处理, 接收者和发送者都没有对方的明确信息, 便于接受者与发送者的解耦.

增强给对象指派职责的灵活性: 链中对象自己并不清楚链结构,他们仅保持一个后继者指针, 因此责任链可简化对象的相互连接, 且可以随时增加或修改处理请求的对象, 增强了给对象指派职责的灵活性.

缺陷: 不保证被接受: 既然一个请求没有明确的接收者, 那么就不能保证它能一定被正确处理, 即一个请求有可能到了链的末端也得不到处理, 或因为没有正确配置链顺序而得不到“正确”处理.

场景

有多个对象可以处理一类请求, 且哪个对象处理由运行时刻自动确定;

在不明确指定接收者的情况下, 向多个对象中提交同一个请求;

处理一个请求的对象集合被动态指定;

Java异常机制: 一个try对应多个catch;

Servlet: Filter链式处理;

Spring MVC : 拦截器链(详见: Spring MVC 实践);

相关模式

Composite(组合)模式: 这种情况下, 一个构件的父构件可作为它的后继者.

原文发布于微信公众号 - Java帮帮(javahelp)

原文发表时间:2017-01-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏racaljk

《代码整洁之道》摘录总结

1.     以下全部条款源于·<Clean Code Robert.C.Martin>Chapter 17,这里对其进行文字层面的加工,简化,便于以后能短时浏...

11530

当Vert.x符合Reactive eXtensions(Vert.x简介的第5部分)

这篇文章是我介绍Eclipse Vert.x系列的第五篇文章。在上一篇文章中,我们看到了Vert.x如何与数据库交互。我们使用Future对象来驯服Vert.x...

22420
来自专栏携程技术中心

干货 | 基于红黑树的高效IP归属地查询方案

作者简介 邢钦华,携程风控团队高级研发经理。2016年加入携程,是风控大数据平台Chloro的设计和开发的主要参与者。专注于大数据流式处理和用户行为分析在互联网...

59090
来自专栏歪先生_自留地

Python test2

12030
来自专栏Java开发者杂谈

分布式改造剧集1

背景介绍 ​ 我所在的项目组,使用的技术一直是接近原始社会的:jdk1.6 + SpringMVC + hessian + Mybatis,当前最火的中间件技术...

30240
来自专栏NetCore

[原创]Fluent NHibernate之旅二--Entity Mapping

接着上一篇,今天我们说说ORM中的Mapping。如果你要体验NHibernate的强大,首先你就要学会配置,包括SessionFactory和Mapping的...

24490
来自专栏学习力

《Java从入门到放弃》框架入门篇:spring中IOC的注入姿势

193100
来自专栏ShaoYL

XCode调试器LLDB

17460
来自专栏禁心尽力

实战技能:小小微信支付业务,何必虚惊一场

记得上次接触微信支付是2016年底,那次也是我程序生涯中首次碰及支付业务,慌张谈不上但是懵逼怀疑时时都有。说起第三方登录或者支付,想必都清楚是直接调用人家现成的...

14620
来自专栏架构师之旅

【强烈推荐】Java工程师如何从一名普通的码农成长为一位大神

本文源自 http://www.hollischuang.com/archives/489 写在前面 java作为一门编程语言,在各类编程语言中...

31680

扫码关注云+社区

领取腾讯云代金券