简介
责任链模 式是一种行为设计模式, 允许你将请求沿着处理者链(单向链表)进行发送。 收到请求后, 每个处理者根据自身条件对请求进行处理, ,如果处理不了则将其传递给链上的下个处理者,以此类推,直到有处理着能对请求进行处理返回,当到达处理者链的最后一个节点也不能处理该请求,则抛出异常。
可以用下图表示责任链设计模式:
为什么用责任链
按照简介,可以用if-else
来代替:
java
if(条件1){
//doSomething
}else if(条件2){
//doSomething
}else if(条件3){
//doSomething
}else{
//doSomething
}
当条件很多的时候,if-else
就变得很多很长,看起来头疼,维护起来也头疼,代码耦合度很高,当需要新增或删除条件的时候,维护成本就很高。责任链的出现就是为了解耦。只需将请求放到处理者链上,处理者链对于请求会有各自的处理方式,更方便二次开发。
责任链结构
抽象处理者(Handler)角色 :定义一个处理请求的抽象方法,包含抽象处理方法和一个后继连接
具体处理者(Concrete Handler)角色 :实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者
客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程
代码实现
抽象处理者(Handler)角色
java
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:
java
public class ExecuteA extends Handler {
@Override
public 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:
java
public class ExecuteB extends Handler {
@Override
public 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:
java
public class ExecuteC extends Handler {
@Override
public 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");
}
}
}
处理传递的对象(额外)
java
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)角色
java
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)角色
java
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;
}
}
执行链表对象:
java
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
java
public class ExecuteA extends Handler {
@Override
public Boolean execute(RequestDemo request) {
if ("A".equals(request.getType())){
System.out.println("A 处理");
return true;
}
return null;
}
}
处理者B
java
public class ExecuteB extends Handler {
@Override
public Boolean execute(RequestDemo request) {
if ("B".equals(request.getType())){
System.out.println("B 处理");
return true;
}
return null;
}
}
处理者C
java
public class ExecuteC extends Handler {
@Override
public Boolean execute(RequestDemo request) {
if ("C".equals(request.getType())){
System.out.println("C 处理");
return true;
}
return null;
}
}
客户类(Client)角色
java
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方法指定下一个执行对象,只需要按顺序放入列表中即可,因为链表已经按顺序执行了,代码变得很简洁。