责任链模式

责任链模式是一种行为设计模式,能够使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。该模式通过将这些对象连接成一条链并沿链传递请求,直到有对象处理它为止。

责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

责任链模式

意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

使用场景:

  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。

  • 可动态指定一组对象处理请求。

  • 在 JAVA WEB 中遇到很多应用。例如,Servlet中的Filter,Struts2中的拦截器栈,就是使用了责任链模式。

责任链模式有两个角色:

  • 抽象处理者(Handler)角色 :定义一个处理请求的接口。如果需要可以定义个一个方法用来设定和返回下家对象的引用。

  • 具体处理者(ConcreteHandler)角色:如果可以处理就处理请求,如果不能处理,就把请求传给下家,让下家处理。也就是说它处理自己能处理的请求且可以访问它的下家。

代码实现

纯责任链模式

在纯责任链模式中,每一个处理者的后继者是由它自己维护的,也就是说那个链条关系是由所有的处理者共同维护的。

下面是一个类似与控制台根据日志级别输出信息的例子,首先定义一个抽象处理者:

public abstract class AbstractLogger {
    public static int ERROR = 1;
    public static int INFO = 2;
    public static int DEBUG = 3;


    protected int level;

    //责任链中的下一个元素
    protected AbstractLogger nextLogger;

    public void setNextLogger(AbstractLogger nextLogger){
        this.nextLogger = nextLogger;
    }

    public void logMessage(int level, String message){
        if(this.level <= level){
            write(message);
        }
        if(nextLogger !=null){
            nextLogger.logMessage(level, message);
        }
    }

    abstract protected void write(String message);

}

下面是一些具体处理者:

public class DebugLogger extends AbstractLogger {

    public DebugLogger(int level){
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Debug::Logger: " + message);
    }
}
public class InfoLogger extends AbstractLogger {
    public InfoLogger(int level){
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Info::Logger: " + message);
    }
}
public class ErrorLogger extends AbstractLogger {
    public ErrorLogger(int level){
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Error::Logger: " + message);
    }
}

客户端测试类:

public class ChainPatternDemo {

    private static AbstractLogger getChainOfLoggers(){

        AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
        AbstractLogger debugLogger = new DebugLogger(AbstractLogger.DEBUG);
        AbstractLogger infoLogger = new InfoLogger(AbstractLogger.INFO);


        debugLogger.setNextLogger(infoLogger);
        infoLogger.setNextLogger(errorLogger);

        return debugLogger;
    }

    public static void main(String[] args) {
        AbstractLogger loggerChain = getChainOfLoggers();

        loggerChain.logMessage(AbstractLogger.DEBUG,
                "This is an debug level information.");

//        loggerChain.logMessage(AbstractLogger.INFO,
//                "This is an info level information.");

//        loggerChain.logMessage(AbstractLogger.ERROR,
//                "This is an error information.");
    }
}
非纯责任链模式

上面纯责任链模式中,链条关系是由所有的处理者共同维护的,我们可以将这个链条维护者抽象出来,并且基于方法的递归调用可以在链上实现来回执行。

下面是一个类似Servlet中Filter功能的例子:

public interface Filter {
    void doFilter(Request req, Response resp, FilterChain chain);
}

定义两个需要过滤的对象:

public class Request {
    //在Request中只保持了一个reqStr字段记录对Request的操作
    //为了方便模拟,没有将reqStr设置为private
    String reqStr;
}

public class Response {
    //在Response中只保持了一个respStr字段记录对Response的操作
    //为了方便模拟,没有将respStr设置为private
    String respStr;
}

具体的处理者:

public class HtmlFilter implements Filter {
    public void doFilter(Request req, Response resp, FilterChain chain) {
        //过滤req.reqStr中的HTML标记
        req.reqStr = req.reqStr.replace("<", "<").replace(">", ">");
        req.reqStr += "---HtmlFilter()---";
        chain.doFilter(req, resp);
        resp.respStr += "---HtmlFilter()---";
    }
}
public class SensitiveFilter implements Filter {
    public void doFilter(Request req, Response resp, FilterChain chain) {
        // 过滤req.reqStr中的敏感词
        req.reqStr = req.reqStr.replace("敏感", "").replace("被就业", "就业");
        req.reqStr += "===SensitiveFilter";
        chain.doFilter(req, resp);
        resp.respStr += "===SensitiveFilter";
    }
}

链条维护者:

public class FilterChain {
    private List<Filter> filters = new ArrayList<Filter>();
    //调用链上的过滤器时,记录过滤器的位置用
    private int index = 0;
    public FilterChain addFilter(Filter f){
        filters.add(f);
        return this;
    }
    public boolean removeFilter(Filter filter)
    {
        if (filters != null && filters.contains(filter))
        {
            return filters.remove(filter);
        }else {
            return false;
        }
    }
    public void doFilter(Request req, Response resp) {
        if(index == filters.size()) return;
        //得到当前过滤器
        Filter f = filters.get(index);
        index++;
        f.doFilter(req, resp, this);
    }
}

客户端测试类:

public class ChainPatternDemo2 {
    public static void main(String[] args) {
        // 需要被过滤的语句
        String msg = "被就业了:),敏感信息,<script>";
        //创建Request、Response对象
        Request req = new Request();
        Response resp = new Response();
        req.reqStr = msg;
        resp.respStr = "response";
        //搞一个过滤链,链上有两个过滤器
        FilterChain chain = new FilterChain();
        chain.addFilter(new HtmlFilter())
                .addFilter(new SensitiveFilter());
        //开始过滤
        chain.doFilter(req, resp);
        System.out.println(req.reqStr);
        System.out.println(resp.respStr);
    }
}

优缺点

优点:
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。

缺点:
1、一是性能问题,每个请求都是从链头遍历到链尾。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值