简介
责任链模式是一种行为设计模式, 允许你将请求沿着处理者链(单向链表)进行发送。 收到请求后, 每个处理者根据自身条件对请求进行处理, ,如果处理不了则将其传递给链上的下个处理者,以此类推,直到有处理着能对请求进行处理返回,当到达处理者链的最后一个节点也不能处理该请求,则抛出异常。
可以用下图表示责任链设计模式:
为什么用责任链
按照简介,可以用if-else
来代替:
if(条件1){//doSomething
}else if(条件2){//doSomething
}else if(条件3){//doSomething
}else{//doSomething
}
当条件很多的时候,if-else
就变得很多很长,看起来头疼,维护起来也头疼,代码耦合度很高,当需要新增或删除条件的时候,维护成本就很高。责任链的出现就是为了解耦。只需将请求放到处理者链上,处理者链对于请求会有各自的处理方式,更方便二次开发。
责任链结构
抽象处理者(Handler)角色:定义一个处理请求的抽象方法,包含抽象处理方法和一个后继连接
具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者
客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程
代码实现
抽象处理者(Handler)角色
public abstract class Handler {Handler next;/*** 使用Boolean类型而不用boolean是为了null这个值,当处理的结果是false时,* 但这个false是对业务有意义的,应该返回。但需要区分出是false还是找不到处理器,此时null就成了有意义的错误值* 用于区分是否找到对应的处理器* @param request 请求对象*/public abstract Boolean execute(RequestDemo request);public void setNext(Handler next) {this.next = next;}
}
具体处理者(Concrete Handler)角色
处理者A:
public class ExecuteA extends Handler {@Overridepublic Boolean execute(RequestDemo request) {//判断是否由当前处理者处理if ("A".equals(request.getType())){System.out.println("A 处理");return true;}else if (next != null){//无法处理则传递给下一个处理者return next.execute(request);}else{//当到达最后一个处理者(最后一个处理者的next为null)还不能处理时,抛出异常(或进行其他处理)throw new RuntimeException("can not find any execute");}}
}
处理者B:
public class ExecuteB extends Handler {@Overridepublic Boolean execute(RequestDemo request) {//判断是否由当前处理者处理if ("B".equals(request.getType())){System.out.println("B 处理");return true;}else if (next != null){//无法处理则传递给下一个处理者return next.execute(request);}else{//当到达最后一个处理者(最后一个处理者的next为null)还不能处理时,抛出异常(或进行其他处理)throw new RuntimeException("can not find any execute");}}
}
处理者C:
public class ExecuteC extends Handler {@Overridepublic Boolean execute(RequestDemo request) {//判断是否由当前处理者处理if ("C".equals(request.getType())){System.out.println("C 处理");return true;}else if (next != null){//无法处理则传递给下一个处理者return next.execute(request);}else{//当到达最后一个处理者(最后一个处理者的next为null)还不能处理时,抛出异常(或进行其他处理)throw new RuntimeException("can not find any execute");}}
}
处理传递的对象(额外)
public class RequestDemo {private String type;public RequestDemo(String type) {this.type = type;}public String getType() {return type;}public void setType(String type) {this.type = type;}
}
客户类(Client)角色
public class NormMain {public static void main(String[] args) {ExecuteA executeA = new ExecuteA();ExecuteB executeB = new ExecuteB();ExecuteC executeC = new ExecuteC();//构建责任链,即构建处理的链表executeA.setNext(executeB);executeB.setNext(executeC);//构建需要处理对象RequestDemo requestDemo = new RequestDemo("C");//责任链的第一个节点开始调用,保证处理是层层往下的,不会忽略某个节点的处理器executeA.execute(requestDemo);}
}
优化版责任链模式
上面的责任链构建方式看起来有点冗余,可以优化一下。在抽象处理者里定义一个有序列表保存所有的处理者,当需要处理请求的时候,对列表进行遍历挑选合适的处理者即可。
抽象处理者(Handler)角色
public abstract class Handler {Handler next;/*** 使用Boolean类型而不用boolean是为了null这个值,当处理的结果是false时,* 但这个false是对业务有意义的,应该返回。但需要区分出是false还是找不到处理器,此时null就成了有意义的错误值* 用于区分是否找到对应的处理器* @param request 请求对象*/public abstract Boolean execute(RequestDemo request);public void setNext(Handler next) {this.next = next;}
}
执行链表对象:
public class HandlerChain {private List<Handler> handlers = new ArrayList<>();public HandlerChain(List<Handler> handlers) {this.handlers = handlers;}public HandlerChain(Handler ...handler) {handlers.addAll(Arrays.asList(handler));}public void addHandler(Handler handler){handlers.add(handler);}public void addHandlers(Handler ...handler){handlers.addAll(Arrays.asList(handler));}public void addHandler(List<List> handler){this.handlers = handlers;}public boolean handleRequest(RequestDemo request) {if (handlers == null || handlers.size() == 0){throw new RuntimeException("can not find any execute");}for (Handler handler : handlers) {Boolean executeResult = handler.execute(request);if (executeResult != null){//找到对应的处理器,处理后应该返回return executeResult ;}}// 如果执行到这里,说明上面的return并没有执行,也就是找不到对应的处理器,此时该抛出异常throw new RuntimeException("can not find any execute");}
}
处理者A
public class ExecuteA extends Handler {@Overridepublic Boolean execute(RequestDemo request) {if ("A".equals(request.getType())){System.out.println("A 处理");return true;}return null;}
}
处理者B
public class ExecuteB extends Handler {@Overridepublic Boolean execute(RequestDemo request) {if ("B".equals(request.getType())){System.out.println("B 处理");return true;}return null;}
}
处理者C
public class ExecuteC extends Handler {@Overridepublic Boolean execute(RequestDemo request) {if ("C".equals(request.getType())){System.out.println("C 处理");return true;}return null;}
}
客户类(Client)角色
public class ListHandlerMain {public static void main(String[] args) {RequestDemo requestDemo = new RequestDemo("C");HandlerChain handlerChain = new HandlerChain(new ExecuteA(),new ExecuteB(),new ExecuteC());handlerChain.handleRequest(requestDemo);}
优点:使用这种含列表方式的责任链的话,不需要调用抽象类的setNext方法指定下一个执行对象,只需要按顺序放入列表中即可,因为链表已经按顺序执行了,代码变得很简洁。