博客信息

责任链模式Chain of Responsibility(行为模式)

发布时间:『 2019-03-30 02:32』  博客类别:23种设计模式  阅读(798)
  • 术语

    Chain of Responsibility:责任链

  • 角色

    Handler 抽象的处理者, 定义了一个处理请求的接口 ConcreteHandlerA , B 具体的处理者, 处理它自己负责的请求, 可以访问它的后继者(即下一个处理者) Request 含义很多属性,表示一个请求

  • 案例

    需求:OA系统请假审批案例

    学生请假1天:教员审批

    学生请假2天:教学主管审批

    学生请假3天:教学经理审批

    学生请假5天:副校长审批

    学生请假超过5天:校长审批

    • 使用前

    package com.javaxl.design.chain.before;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-25 19:30
    */
    public class Request {
      private String content;
      private int day;

      public Request(String content, int day) {
          this.content = content;
          this.day = day;
      }

      public String getContent() {
          return content;
      }

      public void setContent(String content) {
          this.content = content;
      }

      public int getDay() {
          return day;
      }

      public void setDay(int day) {
          this.day = day;
      }
    }


    package com.javaxl.design.chain.before;

    /**
    * @author 小李飞刀
    * @site www.javaxl.com
    * @company
    * @create  2020-02-25 19:31
    */
    public class Handler {

      public void handle(Request request){
          int day = request.getDay();
          if(day <= 1){
              System.out.println("教员处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
          }else if(day <= 2){
              System.out.println("教学主管处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
          }else if(day <= 3){
              System.out.println("教学经理处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
          }else if(day <= 5){
              System.out.println("副校长处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
          }else {
              System.out.println("校长处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
          }
      }
    }


    public class Client {
      public static void main(String[] args) {
          Handler handler = new Handler();
          Request request1 = new Request("小感冒",1);
          handler.handle(request1);

          Request request2 = new Request("做检查",2);
          handler.handle(request2);

          Request request3 = new Request("打点滴",3);
          handler.handle(request3);


          Request request4 = new Request("住院",4);
          handler.handle(request4);

          Request request5 = new Request("在家调养",30);
          handler.handle(request5);
      }
    }

    违背了迪米特法则,调用方清楚的知道整个处理链的存在;

    • 使用后

public class Request {
  private String content;
  private int day;

  public Request(String content, int day) {
      this.content = content;
      this.day = day;
  }

  public String getContent() {
      return content;
  }

  public void setContent(String content) {
      this.content = content;
  }

  public int getDay() {
      return day;
  }

  public void setDay(int day) {
      this.day = day;
  }
}

public abstract class Handler {
  Handler next;
  String name;

  public Handler(String name) {
      this.name = name;
  }

  public Handler getNext() {
      return next;
  }

  public void setNext(Handler next) {
      this.next = next;
  }

  public abstract void handle(Request request);
}

class HandlerA extends Handler {
  public HandlerA(String name) {
      super(name);
  }

  public void handle(Request request) {
      int day = request.getDay();
      if (day <= 1) {
          System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
      } else {
          next.handle(request);
      }
  }
}

class HandlerB extends Handler {
  public HandlerB(String name) {
      super(name);
  }

  public void handle(Request request) {
      int day = request.getDay();
      if (day <= 2) {
          System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
      } else {
          next.handle(request);
      }
  }
}

class HandlerC extends Handler {
  public HandlerC(String name) {
      super(name);
  }

  public void handle(Request request) {
      int day = request.getDay();
      if (day <= 3) {
          System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
      } else {
          next.handle(request);
      }
  }
}

class HandlerD extends Handler {
  public HandlerD(String name) {
      super(name);
  }

  public void handle(Request request) {
      int day = request.getDay();
      if (day <= 5) {
          System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
      } else {
          next.handle(request);
      }
  }
}

class HandlerE extends Handler {
  public HandlerE(String name) {
      super(name);
  }

  public void handle(Request request) {
      int day = request.getDay();
      System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
  }
}


public class Client {
  public static void main(String[] args) {
      HandlerA handlerA = new HandlerA("教员");
      HandlerB handlerB = new HandlerB("教学主管");
      HandlerC handlerC = new HandlerC("教学经理");
      HandlerD handlerD = new HandlerD("副校长");
      HandlerE handlerE = new HandlerE("校长");
      handlerA.setNext(handlerB);
      handlerB.setNext(handlerC);
      handlerC.setNext(handlerD);
      handlerD.setNext(handlerE);

      Request request1 = new Request("小感冒",1);
      handlerA.handle(request1);

      Request request2 = new Request("做检查",2);
      handlerA.handle(request2);

      Request request3 = new Request("打点滴",3);
      handlerA.handle(request3);


      Request request4 = new Request("住院",4);
      handlerA.handle(request4);

      Request request5 = new Request("在家调养",30);
      handlerA.handle(request5);
  }
}

  • 注意事项和细节

    将请求和处理分开,实现解耦,提高系统的灵活性 简化了对象,使对象不需要知道链的结构

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

  • 应用

    springmvc框架~HandlerExcutionChain类 工作流框架绘图生成xml反射实例化,整个流程归档过程 js中的原型链

  

总结

  责任链使用了模板方法和委托的思想构建了一个链表,通过遍历链表来一个个询问链表中的每一个节点谁可以处理某件事情,如果某个节点能够胜任,则直接处理,否则继续向下传递,如果都不能处理next==null,则处理结束。责任链会造成处理的时延,但是能够解耦合,提高可扩展性,使得处理方法的类更专注于处理把自己的事情,便于扩展和改变处理的优先级,应用也非常的广泛。


over......


关键字:     设计模式  

备案号:湘ICP备19000029号

Copyright © 2018-2019 javaxl晓码阁 版权所有