java设计模式之责任链模式

责任链模式

概念

责任链,顾名思义,就是用来处理相关事务责任的一条执行链,执行链上有多个节点,每个节点都有机会(条件匹配)处理请求事务,如果某个节点处理完了就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。

场景一

现实中,请假的OA申请:
请假天数如果是半天到1天,可能直接主管批准即可;
如果是1到3天的假期,需要部门经理批准;
如果是3天到30天,则需要总经理审批;
大于30天,正常不会批准。

类图:

  • 员工提交请求类:LeaveRequest。

  • 抽象的请假责任处理类:AbstractLeaveHandler。

  • 直接主管审批处理类:DirectLeaderLeaveHandler。

  • 部门经理处理类:DeptManagerLeaveHandler。

  • 总经理处理类: GManagerLeaveHandler。

员工请求发起申请到抽象的责任处理类中,根据员工的请假天数,对应的处理类完成处理。 每一个责任处理类设置下面的节点。自身处理不了则传递给下一个节点处理。

代码:

LeaveRequest.java

package com.link.chain.process;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * 请假申请
 */
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LeaveRequest {

 /**天数*/
 private int leaveDays;

 /**姓名*/
 private String name;
}

AbstractLeaveHandler.java

package com.link.chain.process;

/**
 * 请假责任链抽象处理类
 */
public class AbstractLeaveHandler {

 /**
 * 直接主管审批处理的请假天数
 */
 protected int MIN = 1;

 /**
 * 部门经理处理的请假天数
 */
 protected int MIDDLE = 3;

 /**
 * 总经理处理的请假天数
 */
 protected int MAX = 30;

 /**
 * 领导名称
 */
 protected String handlerName;

 /**
 * 下一个处理节点(即更高级别的领导)
 */
 protected AbstractLeaveHandler nextHandler;

 /**
 * 设置下一节点
 */
 protected void setNextHandler(AbstractLeaveHandler handler) {
 this.nextHandler = handler;
 }

 /**
 * 处理请假的请求,子类实现
 */
 protected void handlerRequest(LeaveRequest request) {

 }
}

DirectLeaderLeaveHandler.java

package com.link.chain.process;

/**
 * 主管处理类
 */
public class DirectLeaderLeaveHandler extends AbstractLeaveHandler {

 public DirectLeaderLeaveHandler(String name) {
 this.handlerName = name;
 }

 @Override
 protected void handlerRequest(LeaveRequest request) {
 System.out.println("主管:" + handlerName + ",已经处理;流程结束。");
 if (request.getLeaveDays() <= this.MIN) {
 return;
 }

 if (null != this.nextHandler) {
 this.nextHandler.handlerRequest(request);
 } else {
 System.out.println("审批拒绝!");
 }
 }
}

DeptManagerLeaveHandler.java

package com.link.chain.process;

/**
 * 部门经理处理类
 */
public class DeptManagerLeaveHandler extends AbstractLeaveHandler {

 public DeptManagerLeaveHandler(String name) {
 this.handlerName = name;
 }

 @Override
 protected void handlerRequest(LeaveRequest request) {
 System.out.println("部门经理:" + handlerName + ",已经处理;流程结束。");
 if (request.getLeaveDays() > this.MIN && request.getLeaveDays() <= this.MIDDLE) {
 return;
 }

 if (null != this.nextHandler) {
 this.nextHandler.handlerRequest(request);
 } else {
 System.out.println("审批拒绝!");
 }
 }
}

GManagerLeaveHandler.java

package com.link.chain.process;

/**
 * 总经理处理类
 */
public class GManagerLeaveHandler extends AbstractLeaveHandler {
 public GManagerLeaveHandler(String name) {
 this.handlerName = name;
 }

 @Override
 protected void handlerRequest(LeaveRequest request) {
 System.out.println("总经理:" + handlerName + ",已经处理;流程结束。");
 if (request.getLeaveDays() > this.MIDDLE && request.getLeaveDays() <= this.MAX) {
 return;
 }

 if (null != this.nextHandler) {
 this.nextHandler.handlerRequest(request);
 } else {
 System.out.println("审批拒绝!");
 }
 }
}

Test.java

package com.link.chain.process;

public class Test {
 public static void main(String[] args) {
 LeaveRequest request = LeaveRequest.builder().leaveDays(30).name("小明").build();

 //直接主管
 DirectLeaderLeaveHandler directLeaderLeaveHandler = new DirectLeaderLeaveHandler("陈凡");
 //部门经理
 DeptManagerLeaveHandler deptManagerLeaveHandler = new DeptManagerLeaveHandler("张培进");
 //总经理
 GManagerLeaveHandler gManagerLeaveHandler = new GManagerLeaveHandler("许顺康");

 directLeaderLeaveHandler.setNextHandler(deptManagerLeaveHandler);
 deptManagerLeaveHandler.setNextHandler(gManagerLeaveHandler);
 directLeaderLeaveHandler.handlerRequest(request);
 }
}

场景二

实现下图filter的处理顺序:

request:filter1 >> filter2

response:filter2 >> filter1

执行流程.png

代码:

版本一:

package com.link.chain.filter.v1;

import java.util.ArrayList;
import java.util.List;

/**
 * https://docs.oracle.com/javaee/7/api/
 */
public class Main {
 public static void main(String[] args) {
 Request request = new Request("request");
 Response response = new Response("response");
 FilterChain filterChain = new FilterChain();
 filterChain.add(new HtmlFilter()).add(new SensitiveFilter());
 filterChain.doFilter(request, response);
 System.out.println(request.str);
 }
}

class Request {
 String str;

 Request(String str) {
 this.str = str;
 }
}

class Response {
 String str;

 Response(String str) {
 this.str = str;
 }
}

interface Filter {
 boolean doFilter(Request request, Response response);
}

/**
 * html过滤器
 */
class HtmlFilter implements Filter {

 @Override
 public boolean doFilter(Request request, Response response) {
 request.str += "-->HtmlFilter";
 return false;
 }
}

/**
 * 敏感词过滤器
 */
class SensitiveFilter implements Filter {

 @Override
 public boolean doFilter(Request request, Response response) {
 request.str += "-->SensitiveFilter";
 return false;
 }
}

class FilterChain implements Filter {

 private List<Filter> filters = new ArrayList<>();

 public FilterChain add(Filter filter) {
 filters.add(filter);
 return this;
 }

 @Override
 public boolean doFilter(Request request, Response response) {
 for (Filter filter : filters) {
 filter.doFilter(request, response);
 }
 return false;
 }
}

版本二:

package com.link.chain.filter.v2;

import java.util.ArrayList;
import java.util.List;

/**
 * 用最直观的方式处理response
 * 直接将response的处理放在request下面
 */
public class Main {
 public static void main(String[] args) {
 Request request = new Request("request");
 Response response = new Response("response");
 FilterChain filterChain = new FilterChain();
 filterChain.add(new HtmlFilter()).add(new SensitiveFilter());
 filterChain.doFilter(request, response);
 System.out.println(request.str);
 }
}

class Request {
 String str;

 Request(String str) {
 this.str = str;
 }
}

class Response {
 String str;

 Response(String str) {
 this.str = str;
 }
}

interface Filter {
 boolean doFilter(Request request, Response response);
}

/**
 * html过滤器
 */
class HtmlFilter implements Filter {

 @Override
 public boolean doFilter(Request request, Response response) {
 request.str += "-->HtmlFilter";
 return false;
 }
}

/**
 * 敏感词过滤器
 */
class SensitiveFilter implements Filter {

 @Override
 public boolean doFilter(Request request, Response response) {
 request.str += "-->SensitiveFilter";
 return false;
 }
}

class FilterChain implements Filter {

 private List<Filter> filters = new ArrayList<>();

 public FilterChain add(Filter filter) {
 filters.add(filter);
 return this;
 }

 @Override
 public boolean doFilter(Request request, Response response) {
 for (Filter filter : filters) {
 filter.doFilter(request, response);
 }
 return false;
 }
}

版本三:

package com.link.chain.filter.v3;

import java.util.ArrayList;
import java.util.List;

/**
 * 在filterChain中加入位置的记录
 * 同时在filter中加入第三个参数
 */
public class Main {
 public static void main(String[] args) {
 Request request = new Request("request");
 Response response = new Response("response");
 FilterChain filterChain = new FilterChain();
 filterChain.add(new HtmlFilter()).add(new SensitiveFilter());
 filterChain.doFilter(request, response, filterChain);
 System.out.println(request.str);
 System.out.println(response.str);
 }
}

class Request {
 String str;

 Request(String str) {
 this.str = str;
 }
}

class Response {
 String str;

 Response(String str) {
 this.str = str;
 }
}

interface Filter {
 boolean doFilter(Request request, Response response, FilterChain filterChain);
}

/**
 * html过滤器
 */
class HtmlFilter implements Filter {

 @Override
 public boolean doFilter(Request request, Response response, FilterChain filterChain) {
 request.str += "-->HtmlFilter";
 filterChain.doFilter(request, response, filterChain);
 response.str += "-->HtmlFilter";
 return true;
 }
}

/**
 * 敏感词过滤器
 */
class SensitiveFilter implements Filter {

 @Override
 public boolean doFilter(Request request, Response response, FilterChain filterChain) {
 request.str += "-->SensitiveFilter";
 filterChain.doFilter(request, response, filterChain);
 response.str += "-->SensitiveFilter";
 return true;
 }
}

class FilterChain implements Filter {

 private List<Filter> filters = new ArrayList<>();

 private int index = 0;

 FilterChain add(Filter filter) {
 filters.add(filter);
 return this;
 }

 public boolean doFilter(Request request, Response response, FilterChain filterChain) {
 if (index == filters.size()) {
 return false;
 }
 Filter filter = filters.get(index);
 index++;
 return filter.doFilter(request, response, filterChain);
 }
}

版本四:

package com.link.chain.filter.v4;

import java.util.ArrayList;
import java.util.List;

/**
 * 完全模拟Servlet中的FilterChain
 */
public class Main {
 public static void main(String[] args) {
 Request request = new Request("request");
 Response response = new Response("response");
 FilterChain filterChain = new FilterChain();
 filterChain.add(new HtmlFilter()).add(new SensitiveFilter());
 filterChain.doFilter(request, response);
 System.out.println(request.str);
 System.out.println(response.str);
 }
}

class Request {
 String str;

 Request(String str) {
 this.str = str;
 }
}

class Response {
 String str;

 Response(String str) {
 this.str = str;
 }
}

interface Filter {
 void doFilter(Request request, Response response, FilterChain filterChain);
}

/**
 * html过滤器
 */
class HtmlFilter implements Filter {

 @Override
 public void doFilter(Request request, Response response, FilterChain filterChain) {
 request.str += "-->HtmlFilter";
 filterChain.doFilter(request, response);
 response.str += "-->HtmlFilter";
 }
}

/**
 * 敏感词过滤器
 */
class SensitiveFilter implements Filter {

 @Override
 public void doFilter(Request request, Response response, FilterChain filterChain) {
 request.str += "-->SensitiveFilter";
 filterChain.doFilter(request, response);
 response.str += "-->SensitiveFilter";
 }
}

class FilterChain {

 private List<Filter> filters = new ArrayList<>();

 private int index = 0;

 FilterChain add(Filter filter) {
 filters.add(filter);
 return this;
 }

 public void doFilter(Request request, Response response) {
 if (index < filters.size()) {
 }
 Filter filter = filters.get(index);
 index++;
 filter.doFilter(request, response, this);
 }
}

总结

责任链主要重在责任分离处理,让各个节点各司其职。
责任链上的各个节点都有机会处理事务,但是也可能不会受理请求。
责任链比较长,调试时可能会比较麻烦。
责任链一般用于处理流程节点之类的实际业务场景中。
Spring拦截器链、servlet过滤器链等都采用了责任链设计模式。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 责任链模式 顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个...
    大萌小路阅读 906评论 0 1
  • 一、责任链模式的定义二、责任链模式的使用场景三、责任链模式UML类图四、责任链模式具体实例五、责任链模式代码实现 ...
    Bfmall阅读 1,248评论 0 1
  • 简述 前面我们了解过动态代理模式以及如何自定义拦截器,但是当拦截器存在多个的时候该如何处理呢? 当你要请假时,请假...
    BestbpF阅读 463评论 0 1
  • 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设...
    Mr_Rains阅读 2,317评论 0 48
  • 定义 为避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请...
    Cat9527阅读 341评论 0 0