• 设计模式-13-职责链(责任链)模式


           经典的设计模式有23种,但是常用的设计模式一般情况下不会到一半,我们就针对一些常用的设计模式进行一些详细的讲解和分析,方便大家更加容易理解和使用设计模式。

    1-原理和实现

           职责链模式的英文翻译是Chain Of Responsibility Design Pattern。在GoF的《设计模式》中,它是这么定义的:
           Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
           翻译成中文就是:将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。

            在职责链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过A处理器处理,然后再把请求传递给B处理器,B处理器处理完后再传递给C处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。比如我们经常碰到的Servlet Filter、Spring Interceptor都是这种模式。

           在GoF给出的定义中,如果处理器链上的某个处理器能够处理这个请求,那就不会继续往下传递请求。实际上,职责链模式还有一种变体,那就是请求会被所有的处理器都处理一遍,不存在中途终止的情况。这种变体也有两种实现方式:用链表存储处理器和用数组存储处理器。

    1. public abstract class Handler {
    2. protected Handler successor = null;
    3. public void setSuccessor(Handler successor) {
    4. this.successor = successor;
    5. }
    6. public final void handle() {
    7. doHandle();
    8. if (successor != null) {
    9. successor.handle();
    10. }
    11. }
    12. protected abstract void doHandle();
    13. }
    14. public class HandlerA extends Handler {
    15. @Override
    16. protected void doHandle() {
    17. //...
    18. }
    19. }
    20. public class HandlerB extends Handler {
    21. @Override
    22. protected void doHandle() {
    23. //...
    24. }
    25. }
    26. public class HandlerChain {
    27. private Handler head = null;
    28. private Handler tail = null;
    29. public void addHandler(Handler handler) {
    30. handler.setSuccessor(null);
    31. if (head == null) {
    32. head = handler;
    33. tail = handler;
    34. return;
    35. }
    36. tail.setSuccessor(handler);
    37. tail = handler;
    38. }
    39. public void handle() {
    40. if (head != null) {
    41. head.handle();
    42. }
    43. }
    44. }
    45. // 使用举例
    46. public class Application {
    47. public static void main(String[] args) {
    48. HandlerChain chain = new HandlerChain();
    49. chain.addHandler(new HandlerA());
    50. chain.addHandler(new HandlerB());
    51. chain.handle();
    52. }
    53. }

    2-职责链模式的应用场景示例

          需求:针对用户发表帖子内容判断是否含有敏感词。对于包含敏感词的内容,我们有两种处理方式,一种是直接禁止发布,另一种是给敏感词打马赛克(比如,用***替换敏感词)之后再发布。第一种处理方式符合GoF给出的职责链模式的定义,第二种处理方式是职责链模式的变体。

    1. public interface SensitiveWordFilter {
    2. boolean doFilter(Content content);
    3. }
    4. public class SexyWordFilter implements SensitiveWordFilter {
    5. @Override
    6. public boolean doFilter(Content content) {
    7. boolean legal = true;
    8. //...
    9. return legal;
    10. }
    11. }
    12. // PoliticalWordFilter、AdsWordFilter类代码结构与SexyWordFilter类似
    13. public class SensitiveWordFilterChain {
    14. private List filters = new ArrayList<>();
    15. public void addFilter(SensitiveWordFilter filter) {
    16. this.filters.add(filter);
    17. }
    18. // return true if content doesn't contain sensitive words.
    19. public boolean filter(Content content) {
    20. for (SensitiveWordFilter filter : filters) {
    21. if (!filter.doFilter(content)) {
    22. return false;
    23. }
    24. }
    25. return true;
    26. }
    27. }
    28. public class ApplicationDemo {
    29. public static void main(String[] args) {
    30. SensitiveWordFilterChain filterChain = new SensitiveWordFilterChain();
    31. filterChain.addFilter(new AdsWordFilter());
    32. filterChain.addFilter(new SexyWordFilter());
    33. filterChain.addFilter(new PoliticalWordFilter());
    34. boolean legal = filterChain.filter(new Content());
    35. if (!legal) {
    36. // 不发表
    37. } else {
    38. // 发表
    39. }
    40. }
    41. }

    首先,我们来看,职责链模式如何应对代码的复杂性

           将大块代码逻辑拆分成函数,将大类拆分成小类,是应对代码复杂性的常用方法。应用职责链模式,我们把各个敏感词过滤函数继续拆分出来,设计成独立的类,进一步简化了SensitiveWordFilter类,让SensitiveWordFilter类的代码不会过多,过复杂。

    其次,我们再来看,职责链模式如何让代码满足开闭原则,提高代码的扩展性。

          当我们要扩展新的过滤算法的时候,比如,我们还需要过滤特殊符号,只需要新添加一个Filter类,并且通过addFilter()函数将它添加到FilterChain中即可,其他代码完全不需要修改。假设敏感词过滤框架并不是我们开发维护的,而是我们引入的一个第三方框架,我们要扩展一个新的过滤算法,不可能直接去修改框架的源码。这个时候,利用职责链模式就能达到开篇所说的,在不修改框架源码的情况下,基于职责链模式提供的扩展点,来扩展新的功能。换句话说,我们在框架这个代码范围内实现了开闭原则。除此之外,利用职责链模式相对于不用职责链的实现方式,还有一个好处,那就是配置过滤算法更加灵活,可以只选择使用某几个过滤算法。

  • 相关阅读:
    Linux中shell的使用(零基础学习笔记)
    通用网络协议
    阿里云官方 Redis 开发规范
    【实战技能】单片机bootloader的CANFD,I2C,SPI和串口方式更新APP视频教程(2022-08-01)
    短剧小程序开发,重塑视频观看体验的科技革命
    Mybatis 相关模块以及设计模式分析
    【Linux系统】文件 / 文件夹权限:chmod
    cookie
    MATLAB实战应用-【数据处理篇】数据清洗(从方法论到实战应用)
    常用 时间类型的相互转化
  • 原文地址:https://blog.csdn.net/ycmy2017/article/details/134506117