软件体系结构--责任链模式

概念

责任链模式为某个请求创建一个对象链,每个对象依次检查此请求,并对其进行处理,或者将它传给链中的下一个对象。

链表是很常见一种数据结构,责任链模式的结构其实和链表相差无几,唯一的区别就是责任链模式中所有的对象都有一个共同的父类(或接口):

image

在责任链模式中,N个 Handler 子类都处理同一个请求,只不过具体的职责有所差别。

当有一个请求进入时,先经过 AHandler 的 handlerRequest 方法,然后再把请求传递给 BHandler,B 处理完再把请求传递给 CHandler,以此类推,形成一个链条。链条上的每一个对象所承担的责任各不相同,这就是责任链模式。

例子

现在我们模拟一个场景:论坛用户发表帖子,但是常常会有用户一些不良的信息,如广告信息,涉黄信息,涉及政治的敏感词等。这时我们就可以使用责任链模式来过滤用户发表的信息。

先定义所有责任链对象的父类:

/**
 * 帖子处理器
 */
public abstract class PostHandler {

    /**
     * 后继者
     */
    protected PostHandler successor;

    public void setSuccessor(PostHandler handler){
        this.successor = handler;
    }

    public abstract void handlerRequest(Post post);

    protected final void next(Post post){
        if(this.successor != null){
            this.successor.handlerRequest(post);
        }
    }
}

父类 Handler 主要封装了传递请求等方法,其中要注意的有两点:

  • successor,后继者,这个属性很重要,它保存了责任链中下一个处理器
  • 在 next() 方法中(方法名自己随便取),当请求传递到最后一个责任对象时,已经没有后继者继续处理请求了,因此要对 successor 做判空处理,避免抛出空指针异常。
  • 处理请求的handlerRequest 的入参和返回类型可以根据实际情况修改,可以在该方法中抛出异常来中断请求

广告处理器:

/**
 * 广告处理器
 */
public class AdHandler extends PostHandler {

    @Override
    public void handlerRequest(Post post) {
        //屏蔽广告内容
        String content = post.getContent();
        //.....
        content = content.replace("广告","**");
        post.setContent(content);

        System.out.println("过滤广告...");
        //传递给下一个处理器
        next(post);
    }
}

涉黄处理器:

/**
 * 涉黄处理器
 */
public class YellowHandler extends PostHandler {

    @Override
    public void handlerRequest(Post post) {
        //屏蔽涉黄内容
        String content = post.getContent();
        //.....
        content = content.replace("涉黄","**");
        post.setContent(content);

        System.out.println("过滤涉黄内容...");
        //传递给下一个处理器
        next(post);
    }
}

调用:

//创建责任对象
PostHandler adHandler = new AdHandler();
PostHandler yellowHandler = new YellowHandler();
PostHandler swHandler = new SensitiveWordsHandler();

//形成责任链
yellowHandler.setSuccessor(swHandler);
adHandler.setSuccessor(yellowHandler);

Post post = new Post();
post.setContent("我是正常内容,我是广告,我是涉黄,我是敏感词,我是正常内容");

System.out.println("过滤前的内容为:"+post.getContent());

post = adHandler.handlerRequest(post);

System.out.println("过滤后的内容为:"+post.getContent());

总结

可能大家有疑问,为什么不把所有的过滤器写在一个方法里呢?因为这样做又破坏了开放封闭原则。我们需要使用责任链模式,能够在不修改已有代码的情况下扩展新功能。

责任链模式将常用于过滤器,拦截器,事件(鼠标键盘事件,冒泡事件等)等场景

优点

  • 请求者和接收者解耦
    可以动态的增加或减少责任链上的对象,或者修改顺序

缺点

  • 调用者不知道请求可能被哪些责任链对象处理,不利于排错
    用户请求可能被责任链中途拦截,最终未必被真正执行,这点既是优点也是缺点,我们可以利用它做权限控制拦截器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值