设计模式-行为型-责任链模式

119 阅读3分钟

简介

责任链模式又称职责链模式,是行为型模式的一种。责任链模式是23种设计模式种较难的一种,在一些大型的框架中就有责任链的身影,如Tomcat容器的过滤器,SpringMVC的拦截器等等。责任链的核心就是在系统中有多个任务处理者,对于某一个事件,每个处理者会判断自己能不能处理,如果能则处理,不能则往下传,直到有人处理为止。责任链就好像我们公司的审批一样,有的审批小组长就可以搞定,有的审批需要到部门老大那里,有的需要到部门经理那里,如果前面都不能处理,最后会流到老板那里。其实现有两种:第一种是传统的实现,在处理者中指定下一个处理者,第二种是将所有处理者放到一个list中,此时加入的顺序就很重要了。接下来就分别对这两种做代码示例。

传统实现

假设我们是一个出版社,收到了一个投稿文章,此时我们有格式审核部门、文字审核部门和最终专家质量审核。当我们比较闲时,会先审核格式,然后再去审核文字是否有敏感词汇和错别字,完了交给专家审核,最后将所有审核意见返回给作者。
1.定义一个Handler抽象类,然后FormatHandler/WordHandler/QualityHandler继承Handler

public abstract class Handler {
    protected Handler nextHandler;
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract String handRequest(String content);
}
public class FormatHandler extends Handler{
    @Override
    public String handRequest(String content) {

        String formatContent = checkFormatMsg(content);
        if (null != this.nextHandler) {
            return this.nextHandler.handRequest(formatContent);
        }
        return formatContent;
    }

    private String checkFormatMsg(String content) {
        System.out.println("Check format");
        return content + "->checkFormat";

    }
}
public class WordHandler extends Handler{
    @Override
    public String handRequest(String content) {
        String newContent = checkError(content);
        if (null != this.nextHandler) {
            return this.nextHandler.handRequest(newContent);
        }
        return newContent;
    }

    private String checkError(String content) {
        System.out.println("Check error");
        return content + "->checkError";
    }
}
public class QualityHandler extends Handler {
    @Override
    public String handRequest(String content) {
        String newContent = checkQuality(content);
        if (null != this.nextHandler) {
            return this.nextHandler.handRequest(newContent);
        }
        return newContent;
    }

    private String checkQuality(String content) {
        System.out.println("Check quality");
        return content + "->checkQuality";
    }
}

2.客户端调用

public class Test {
    public static void main(String[] args) {
        Handler formatHandler = new FormatHandler();
        Handler errorHandler = new WordHandler();
        Handler qualityHandler = new QualityHandler();

        formatHandler.setNextHandler(errorHandler);
        errorHandler.setNextHandler(qualityHandler);

        System.out.println(formatHandler.handRequest("hello world"));
        /**
         * Check format
         * Check error
         * Check quality
         * hello world->checkFormat->checkError->checkQuality
         */
    }
}

使用list实现

接上面的场景,当我们现在很忙时,我们的步骤就是首先审核格式,如果格式有问题直接返回,错别字审核和质量审核以此类推。
1.定义一个IRequest接口,然后ContentRequest接口实现它,该接口主要时用于存储和获取事件在链中处理时的数据。

public interface IRequest {
    void putEle(String key, Object value);

    Object getEle(String key);
}
import java.util.HashMap;
import java.util.Map;

public class ContentRequest implements IRequest{

    private Map<String, Object> request = new HashMap<>();

    @Override
    public void putEle(String key, Object value) {
        request.put(key, value);
    }

    @Override
    public Object getEle(String key) {
        return request.getOrDefault(key, null);
    }
}

2.定义IResponse接口,然后ContentResponse实现它,其主要作用时用于决定是否还需要向链的下游流去。

public interface IResponse {
    boolean getEndStatus();

    void setEndStatus(boolean end);
}
public class ContentResponse implements IResponse{

    private boolean end = false;

    @Override
    public boolean getEndStatus() {
        return end;
    }

    @Override
    public void setEndStatus(boolean endStatus) {
        this.end = endStatus;
    }

}

3.定义Handler接口,然后FormatHandler/WordHandler/QualityHandler实现Handler

public class FormatHandler implements Handler{

    @Override
    public void hand(IRequest request, IResponse response) {
        String content = (String)request.getEle("content");
        if (content.contains("formatError")) {
            response.setEndStatus(true);
            request.putEle("endReason", "format error");
        }
    }
}
public class WordHandler implements Handler{
    @Override
    public void hand(IRequest request, IResponse response) {
        String content = (String)request.getEle("content");
        if (content.contains("wordError")) {
            response.setEndStatus(true);
            request.putEle("endReason", "word error");
        }
    }
}
public class QualityHandler implements Handler{
    @Override
    public void hand(IRequest request, IResponse response) {
        String content = (String)request.getEle("content");
        if (content.contains("qualityError")) {
            response.setEndStatus(true);
            request.putEle("endReason", "quality error");
        }
    }
}

4.定义一个执行引擎,用于创建和执行事件链

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

public final class HandlerEngine {
    private final List<Handler> handlerChain = new ArrayList<>();
    public void addHandler(Handler... handlers) {
        for (Handler handler : handlers) {
            handlerChain.add(handler);
        }
    }

    public void executeHandler(IRequest request, IResponse response) {
        for (Handler handler : handlerChain) {
            handler.hand(request, response);
            if (response.getEndStatus()) {
                return;
            }
        }
    }

}

5.客户端调用

public class Test {
    public static void main(String[] args) {
        String content1 = "formatError_quality1Error_word1Error";
        String content2 = "format1Error_qualityError_word1Error";
        String content3 = "format1Error_quality1Error_wordError";
        String content4 = "format1Error_quality1Error_word1Error";
        System.out.println(test(content1));//Paper not accept, reason of format error
        System.out.println(test(content2));//Paper not accept, reason of quality error
        System.out.println(test(content3));//Paper not accept, reason of word error
        System.out.println(test(content4));//Paper accept
    }

    private static String test(String content) {
        Handler formatHandler = new FormatHandler();
        Handler wordHandler = new WordHandler();
        Handler qualityHandler = new QualityHandler();
        HandlerEngine engine = new HandlerEngine();
        engine.addHandler(formatHandler, wordHandler, qualityHandler);
        IRequest request = new ContentRequest();
        request.putEle("content", content);
        IResponse response = new ContentResponse();
        engine.executeHandler(request, response);
        String endReason = (String)request.getEle("endReason");
        String res = null != endReason ? "Paper not accept, reason of " + endReason : "Paper accept";
        return res;
    }
}