设计模式之责任链模式

简介

责任链模式是一种行为设计模式, 允许你将请求沿着处理者链(单向链表)进行发送。 收到请求后, 每个处理者根据自身条件对请求进行处理, ,如果处理不了则将其传递给链上的下个处理者,以此类推,直到有处理着能对请求进行处理返回,当到达处理者链的最后一个节点也不能处理该请求,则抛出异常。
可以用下图表示责任链设计模式:
设计模式之责任链模式_第1张图片

为什么用责任链

按照简介,可以用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 {
    @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

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

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");
        }
    }
}

处理传递的对象(额外)

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 {
    @Override
    public Boolean execute(RequestDemo request) {
        if ("A".equals(request.getType())){
            System.out.println("A 处理");
            return true;
        }
        return null;
    }
}

处理者B

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

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)角色

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方法指定下一个执行对象,只需要按顺序放入列表中即可,因为链表已经按顺序执行了,代码变得很简洁。

你可能感兴趣的:(java,设计模式,责任链模式,java)