上文(设计模式-命令模式):https://blog.csdn.net/qq_16498553/article/details/106591438
目录
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
背景
基本每个在职人员,都经历过请假的事情。正常情况下,请假需要经过上级部门领导审批,而公司有总经理、部门经理、组长 有的甚至更多职位。请假也分为很多种情况,比如,事假、病假、调休假,这种一般组长就可以给你审批了。而像产假或特殊长休假有的公司是根据请假长短来判断,有的是根据类型,需要到经理甚至总经理来审批,而责任链模式是解决这种根据不同场景需要不同级别的来处理的一种模式。
责任链模式是什么?
责任链模式(Chain of Responsibility Pattern)属于行为型模式,客户端发出一个请求,链上的对象都有机会处理这一请求,使多个对象都有机会处理请求,从而避免请求的发送都和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
角色:
抽象处理者角色(Handler):定义处理请求的接口或方法,包含抽象处理方法和一个后继连接。
具体处理者角色(ConcreteHandler):实现抽象处理的方法,接收客户端的请求判断是否能够处理本次请求,若能处理则处理,否则传送本次请求给后继者。
客户端(Client):向链路发起请求的用户,让链路负责处理。
责任链模式可以干嘛?
如果用户请求了一次,但是同一个链上有多个对象可以进行处理,并且最后具体是由哪个进行处理,是由该用户请求的信息和连上的对象结合起来动态决定的,这种对象就可以使用责任链模式。
个人理解:
比如,公司里一个员工要请假,但是最终批的领导是不确定的,直属上级领导还是哪一层领导,因为该审批是由员工提交的请假申请类型和上层领导审批权而决定的,比如普通事假直属上层就直接审批了,而请个十天半个月可能直接需要到总经理来审批了。审批是一层一层传递实际上是一个递归调用。
优点:
降低耦合度:它将请求的发送者和接收者解耦,请求都可以不用知道是谁来处理的,处理者可以不用知道请求是的全部信息,双方都解耦,提高了系统的灵活性。
缺点:
降低性能:由于每个请求基本都需要经历过递归遍历,特别是链路相当长的时候,遍历需要耗费的时间相当长,会导致请求的影响时间降低。
调试繁琐:每一个请求基本都需要递归遍历,所以当链路长的时候调试相当繁琐;
死循环:如果处理不当可能造成死循环;
责任链模式类图
实现代码
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
/**
* @Auther: csh
* @Date: 2020/6/4 11:31
* @Description:抽象员工(抽象)
*/
public interface IEmployee {
//请假类型
int getType();
//请假原因
String getRequest();
}
/**
* @Auther: csh
* @Date: 2020/6/4 11:43
* @Description:
*/
public class Employee implements IEmployee {
/**
*
* 功能描述:职位类型
*
* 1.普通员工
* 2.组长
* 3.部门经理
*
* @param:
* @return:
* @auther: csh
* @date: 2020/6/4 11:44
*/
private int type=1;
//妇女的请示
private String request= "";
@Override
public int getType() {
return type;
}
@Override
public String getRequest() {
return request;
}
public Employee(int type, String request) {
this.type = type;
switch (this.type){
case 1:
this.request="员工的请求是:"+request;
break;
case 2:
this.request="组长的请求是:"+request;
break;
case 3:
this.request="经理的请求是:"+request;
break;
}
}
}
/**
* @Auther: csh
* @Date: 2020/6/4 14:25
* @Description:拥有审批权的负责人(handler)
*/
public abstract class Handler {
public final static int GROUP_LEVEL_PEQUEST =1;
public final static int DEPARTMENT_LEVEL_REQUEST=2;
public final static int BOOS_LEVEL_REQUEST=3;
//能批的假级别
private int level = 0;
//责任传递,一个人责任人是谁
private Handler nexHandler;
public Handler() {
}
public Handler(int level) {
this.level = level;
}
//请求文本
public final void handlerMessage(IEmployee employee){
if(employee.getType()==this.level){
this.response(employee);
}else{
if(this.nexHandler!=null){
this.nexHandler.handlerMessage(employee);
}else{
System.out.println("----大boos,直接过------");
}
}
}
public void setNext(Handler handler){
this.nexHandler = handler;
}
//回应批复结果
protected abstract void response(IEmployee employee);
}
/**
* @Auther: csh
* @Date: 2020/6/4 14:32
* @Description:组长
*/
public class GroupManager extends Handler {
public GroupManager() {
}
public GroupManager(int level) {
super(Handler.GROUP_LEVEL_PEQUEST);
}
@Override
protected void response(IEmployee employee) {
System.out.println("---下属的请示-------");
System.out.println(employee.getRequest());
System.out.println("组长回复是:同意\n");
}
}
/**
* @Auther: csh
* @Date: 2020/6/4 11:43
* @Description:部门经理
*/
public class DepartmentManager extends Handler {
public DepartmentManager() {
}
public DepartmentManager(int level) {
super(Handler.DEPARTMENT_LEVEL_REQUEST);
}
@Override
protected void response(IEmployee employee) {
System.out.println("---下属的请示-------");
System.out.println(employee.getRequest());
System.out.println("部门经理回复是:同意\n");
}
}
/**
* @Auther: csh
* @Date: 2020/6/4 11:43
* @Description:老板
*/
public class Boos extends Handler {
public Boos() {
}
public Boos(int level) {
super(Handler.BOOS_LEVEL_REQUEST);
}
@Override
protected void response(IEmployee employee) {
System.out.println("---下属的请示-------");
System.out.println(employee.getRequest());
System.out.println("老板回复是:同意\n");
}
}
/**
* @Auther: csh
* @Date: 2020/6/4 14:36
* @Description:演示 责任链模式
* 演示 员工申请的假由组长批、组长申请的假由部门经理批、部门经理申请的假由老板批;
*/
public class Client {
public static void main(String[] args) {
//随机先成几个员工
ArrayList<IEmployee> arrayList = new ArrayList <IEmployee>();
for(int i=0;i<10;i++){
arrayList.add(new Employee(getRandom(1,3),"家里有事"));
}
//定义三个请示对象
Handler groupManager = new GroupManager(Handler.GROUP_LEVEL_PEQUEST);
Handler deparmentManager= new DepartmentManager(Handler.DEPARTMENT_LEVEL_REQUEST);
Handler boos = new Boos(Handler.BOOS_LEVEL_REQUEST);
groupManager.setNext(deparmentManager);
deparmentManager.setNext(boos);
for (IEmployee iEmployee : arrayList) {
groupManager.handlerMessage(iEmployee);
}
}
//随机数
public static int getRandom(int start,int end) {
int num=(int) (Math.random()*(end-start+1)+start);
return num;
}
}
结果
---下属的请示-------
员工的请求是:家里有事
组长回复是:同意
---下属的请示-------
员工的请求是:家里有事
组长回复是:同意
---下属的请示-------
经理的请求是:家里有事
老板回复是:同意
---下属的请示-------
经理的请求是:家里有事
老板回复是:同意
---下属的请示-------
组长的请求是:家里有事
部门经理回复是:同意
---下属的请示-------
经理的请求是:家里有事
老板回复是:同意
---下属的请示-------
员工的请求是:家里有事
组长回复是:同意
---下属的请示-------
经理的请求是:家里有事
老板回复是:同意
---下属的请示-------
组长的请求是:家里有事
部门经理回复是:同意
---下属的请示-------
经理的请求是:家里有事
老板回复是:同意
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
最后
责任链模式是通过用户发起一个请求,然后责任链上有很多处理对象,当用户所符合某一个处理对象的条件时,处理对象对这个请求进行处理。这里其实请求者是不清楚最后被哪个处理对象处理,而处理者也不需要知道这个处理者的全部信息,所以双方都起到一个很好的解耦,当然责任链上的处理职责是可以动态增减的,用户无需知道,起到一个非常好的灵活性。
用到责任链场景/应用:
Netty 中的ChannelHandler
Spring AOP 是通过责任链来管理
Dubbo 的Filter 过滤器链也是通过责任链管理如:TimeoutFilter、TimeoutFiltert等
Java Web中的过滤器链
Struts2中的拦截器栈
Tomcat Filter
javax.servlet.Filter 接口
.....