lizema lizema
首页
  • js

    • js
  • Git相关

    • 《Git》
  • 设计模式

    • 设计模式
  • java
  • jdk
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • HTML
  • CSS
  • 学习方法
  • 敏捷开发心得
  • 心情杂货
  • 实用技巧
  • GPT相关
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

malize

各自努力,顶峰相见。
首页
  • js

    • js
  • Git相关

    • 《Git》
  • 设计模式

    • 设计模式
  • java
  • jdk
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • HTML
  • CSS
  • 学习方法
  • 敏捷开发心得
  • 心情杂货
  • 实用技巧
  • GPT相关
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 工作中用到的设计模式
  • 享元模式
  • 单例模式
  • 原型模式
  • 备忘录模式
  • 外观模式
  • 工厂方法模式
  • 模板方法模式
  • 策略模式
  • 装饰模式
  • 访问者模式
  • 责任链模式
    • 适配器模式
    • 中介者模式
    • 设计模式
    malize
    2020-11-18
    目录

    责任链模式

    # 责任链模式

    # 一、责任链模式

    1. 原理:责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。

    2. 优缺点

      1. 1 优点
      • 解耦责任对象:责任链模式将请求的发送者和接收者解耦,发送者无需知道具体的接收者是谁,也无需知道请求将由谁处理。
      • 灵活性和可扩展性:由于责任链中的每个处理器都是独立的对象,因此可以根据需要轻松地添加、删除或调整处理器,而不会影响其他部分的代码。
      • 单一职责原则:每个处理器只需关注自己能处理的请求,遵循了单一职责原则,使得代码更加清晰和易于维护。
      • 动态组装处理器链:可以根据实际情况动态地组装责任链,根据请求的特征或条件决定由哪些处理器来处理请求。
      • 降低耦合度:将请求的发送者和接收者解耦,使得系统的各个部分可以独立地进行修改、扩展或调整,降低了系统各模块之间的耦合度。
      1. 2 缺点
      • 请求处理不确定性:由于请求的处理是由一系列处理器依次处理的,如果责任链较长或者处理器不当,可能导致请求处理的结果不确定性增加。
      • 性能问题:责任链模式可能导致请求需要遍历整个责任链才能被处理,当责任链较长或者处理器的处理逻辑较复杂时,可能会影响性能。
      • 可能造成循环引用:如果责任链中的某个处理器的逻辑错误导致调用了自身,可能会导致无限循环,甚至引发栈溢出错误。
      • 难以调试:责任链模式的处理器是独立的,处理请求的具体逻辑可能分散在多个处理器中,这可能会增加调试的难度。
      • 可能导致请求丢失:如果责任链中没有一个处理器能够处理请求,可能会导致请求被丢弃,而不是得到一个明确的处理结果。
    3. 适用场景

      • 远程代理(Remote Proxy):用于控制对远程对象的访问。例如,RMI(远程方法调用)使用代理模式来实现客户端对远程对象的方法调用。
      • 虚拟代理(Virtual Proxy):用于控制对资源密集型对象的访问。比如,在图片浏览器中,只有在真正需要显示图片时才去加载图片,而不是一次性加载所有图片。
      • 延迟加载(Lazy Initialization):当创建一个对象非常耗时,而该对象在程序运行中不一定会被使用时,可以使用虚拟代理来延迟对象的创建,直到真正需要它时才进行创建。
      • 保护代理(Protection Proxy) :用于控制对象的访问权限。可以在代理中对客户端的请求进行预处理,检查客户端是否具有访问目标对象的权限。例如,用户权限管理系统中,通过保护代理来控制不同用户对特定资源的访问权限。

      • 智能代理(Smart Proxy):可以在访问对象时附加一些额外的功能,例如日志记录、性能监控、事务管理等。例如,在数据库操作中,可以通过代理模式实现自动的事务管理。

      • 缓存代理(Cache Proxy):用于缓存某些操作的结果,以提高系统性能。例如,计算结果缓存代理可以缓存一些复杂计算的结果,避免每次都进行重复计算。

    # 二、责任链模式基本代码

    1. 公共接口

      public interface Handler {
          void handleRequest(Request request);
      }
      
      1
      2
      3
    2. 具体处理类

      public class ConcreteHandler1 implements Handler {
          private Handler nextHandler;
      
          @Override
          public void handleRequest(Request request) {
              if (request.getType().equals(RequestType.TYPE1)) {
                  System.out.println("ConcreteHandler1 is handling the request...");
                  // 处理请求
              } else if (nextHandler != null) {
                  // 无法处理,传递给下一个处理器
                  nextHandler.handleRequest(request);
              }
          }
      
          public void setNextHandler(Handler nextHandler) {
              this.nextHandler = nextHandler;
          }
      }
      
      public class ConcreteHandler2 implements Handler {
          private Handler nextHandler;
      
          @Override
          public void handleRequest(Request request) {
              if (request.getType().equals(RequestType.TYPE2)) {
                  System.out.println("ConcreteHandler2 is handling the request...");
                  // 处理请求
              } else if (nextHandler != null) {
                  // 无法处理,传递给下一个处理器
                  nextHandler.handleRequest(request);
              }
          }
      
          public void setNextHandler(Handler nextHandler) {
              this.nextHandler = nextHandler;
          }
      }
      
      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
    3. 请求类

      public class Request {
          private RequestType type;
      
          public Request(RequestType type) {
              this.type = type;
          }
      
          public RequestType getType() {
              return type;
          }
      }
      
      public enum RequestType {
          TYPE1, TYPE2 // 定义两种请求类型
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
    4. 客户端

      public class Client {
          public static void main(String[] args) {
              // 创建责任链
              Handler handler1 = new ConcreteHandler1();
              Handler handler2 = new ConcreteHandler2();
              handler1.setNextHandler(handler2);
      
              // 创建请求
              Request request1 = new Request(RequestType.TYPE1);
              Request request2 = new Request(RequestType.TYPE2);
      
              // 处理请求
              handler1.handleRequest(request1);
              handler1.handleRequest(request2);
          }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16

    # 三、实现方式

    1. 声明处理者接口并描述请求处理方法的签名。

      确定客户端如何将请求数据传递给方法。 最灵活的方式是将请求转换为对象, 然后将其以参数的形式传递给处理函数。

    2. 为了在具体处理者中消除重复的样本代码, 你可以根据处理者接口创建抽象处理者基类。

      该类需要有一个成员变量来存储指向链上下个处理者的引用。 你可以将其设置为不可变类。 但如果你打算在运行时对链进行改变, 则需要定义一个设定方法来修改引用成员变量的值。

      为了使用方便, 你还可以实现处理方法的默认行为。 如果还有剩余对象, 该方法会将请求传递给下个对象。 具体处理者还能够通过调用父对象的方法来使用这一行为。

    3. 依次创建具体处理者子类并实现其处理方法。 每个处理者在接收到请求后都必须做出两个决定:

      • 是否自行处理这个请求。
      • 是否将该请求沿着链进行传递。
    4. 客户端可以自行组装链, 或者从其他对象处获得预先组装好的链。 在后一种情况下, 你必须实现工厂类以根据配置或环境设置来创建链。

    5. 客户端可以触发链中的任意处理者, 而不仅仅是第一个。 请求将通过链进行传递, 直至某个处理者拒绝继续传递, 或者请求到达链尾。

    6. 由于链的动态性, 客户端需要准备好处理以下情况:

      • 链中可能只有单个链接。
      • 部分请求可能无法到达链尾。
      • 其他请求可能直到链尾都未被处理。
    编辑 (opens new window)
    #重学Java设计模式
    访问者模式
    适配器模式

    ← 访问者模式 适配器模式→

    最近更新
    01
    其他
    02
    其他
    03
    名人总结
    08-27
    更多文章>
    Theme by Vdoing
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式