责任链模式 必备的责任链设计模式

深度报道

概念

责任链模式使得多个对象有机会处理同一个请求,从而避免了请求的发送方和接收方之间的耦合关系。将这些对象连接成一个链,并沿着这个链传递请求,直到有一个对象处理它。

链表VS责任链

责任链模式为请求创建一个对象链,每个对象依次检查请求并处理它,或者将其传递给链中的下一个对象。链表是一种非常常见的数据结构。链表中的每个节点都是一个对象,下一个节点的指针存储在该对象中。链表的基本结构如下:责任链模式的结构其实和链表非常相似,不同的是责任链模式中的所有对象都有一个共同的父类:

在责任链模式中,所有n个Handler子类处理相同的请求,但是具体的责任是不同的。当一个请求进来时,它首先通过一个Handler的HandlerRequest方法,然后将请求传递给一个handler,B处理后将请求传递给CHandler,以此类推,形成一个链。链条中的每个对象承担不同的责任。这就是责任链模型。现在我们模拟一个场景:论坛用户发帖,但是经常会有用户发一些不好的信息,比如广告信息,色情相关的信息,政治相关的敏感词等等。此时,我们可以使用责任链模型来过滤用户发布的信息。首先,定义所有责任链对象的父类:

/**

*后处理器

*/

publicatabstractclassposhandler {

/**

*继任者

*/

protectedPostHandlersuccessor

publicvoidsetSuccessor后继者{

this .后继=处理程序;

}

publicatabstractvoidhandlerrequest;

protectedfinalvoidnext{

如果{

this .继承者. handlerrequest;

}

}

}

父类Handler主要封装传递请求等方法,其中需要注意以下几点:

在后继方法中,当请求被传递到最后一个负责对象时,没有后继者继续处理请求,因此应该判断后继者空以避免抛出空指针异常。

处理请求的handlerRequest的输入和返回类型可以根据实际情况进行修改,并且可以在这个方法中抛出一个异常来中断请求。

Ad处理器:

/**

*广告处理器

*/

public class adhandlerelextendsPostHandler {

@覆盖

publicvoidhandlerRequest {

//阻止广告内容

Stringcontent = post.getContent

// .....

content = content.replace

post.setContent

system . out . println;

//传递到下一个处理器

接下来;

}

}

黄色处理器:

/**

*黄色处理器

*/

public classyellohandlerextendsposthandler {

@覆盖

publicvoidhandlerRequest {

//屏蔽黄色内容

Stringcontent = post.getContent

// .....

content = content.replace

post.setContent

system . out . println;

//传递到下一个处理器

接下来;

}

}

敏感文字处理器:

/**

*敏感文字处理器

*/

public classsensitwordshandlerextendsposhandler {

@覆盖

publicvoidhandlerRequest {

//屏蔽敏感词

Stringcontent = post.getContent

// .....

content = content.replace

post.setContent

system . out . println;

//传递到下一个处理器

接下来;

}

}

三个责任链对象的结构基本相同,但具体的业务处理逻辑不同。在上面的代码中,所有不健康的内容都用“*”替换。调用:

//创建责任对象

post handlerradhandler = new hadhandler;

post handleleryellowhandler = new yellowhandler;

post handlers whandler = newSensitiveWordsHandler;

//形成责任链

yellowHandler.setSuccessor后继者;

adhandler . set后继者;

Postpost = newPost

post.setContent

system . out . println);

post = adHandler.handlerRequest

system . out . println);

通话结果:看到这个,相信你已经基本掌握了责任链模式。但问题是。我就不能用一种方法写出不好的过滤信息吗?例如:

publicclassPostUtil{

publicvoidfilterContent{

Stringcontent = post.getContent

content = content.replace

content = content.replace

content = content.replace

post.setContent

}

}

相比之下,这种方法更简单,只需几行代码就可以修复它。为什么使用责任链模型?你还记得开放封闭的原则吗?如果以后要添加其他函数,过滤其他类型的内容,就要修改上面的filterContent方法,这就违反了打开关闭原则。如果你是框架开发者,你希望别人修改你框架的源代码吗?因此,我们需要使用责任链模型,它可以在不修改现有代码的情况下扩展新的功能。经典案例1。servlet中的过滤器servlet中的过滤器是一种典型的责任链模式。如果我们想为每个Http请求打印一个日志,我们可以使用Filter Filter来实现它:创建一个过滤器来实现过滤器接口:

publicclasslogfilterimplesfilter { 0

@覆盖

publicationinitthrowsservletexception {

}

@覆盖

public votidofilterthrowsio exception,ServletException{

system . out . println;

filterChain.doFilter

}

@覆盖

publicvoiddestroy {

}

}

然后将此过滤器配置为web.xml:

日志过滤器

com.zhoujun.filter.LogFilter

日志过滤器

/*

在上面的LogFilter类中,我们可以看到servlet的责任链是通过Filter来实现的,FilterChain是一个接口,doFilter中也使用了Filter chain,也是一个接口。通过搜索源代码,我们找到了FilterChain的一个实现类:

public class passthroughfilterchain implements filterchain {

@可空

privateFilterfilter

@可空

privatefilterchainextfilterchain;

@可空

privateServletservlet

publicPassThroughFilterChain {

Assert.notNull

Assert.notNull

this.filter = filter

this . nextFilterChain = nextFilterChain;

}

publicPassThroughFilterChain {

Assert.notNull

this.servlet = servlet

}

public votidofilterthrowsservletexception,IOException{

如果{

this . filter . DoFilter;

}else{

Assert.state

this . servlet . service;

}

}

}

请仔细看一下这个实现类,你会发现它的结构和我们之前的PostHandler示例代码非常相似,这个类中的private filter chain next filter chain;相当于后置处理器中的继任者。将我们的自定义Filter配置成web.xml的操作是将对象添加到责任链中,Servlet开发人员帮助我们完成了set后继者的操作。

责任链设计模式也广泛应用于Spring、Dubbo、Mybatis等框架中。总结责任链模式常用于过滤器、拦截器、事件等场景。优势

请求者和接收者的解耦;

您可以动态增加或减少责任链中的对象,或者修改顺序。

劣势

调用者不知道请求可能会处理哪些责任链对象,不利于故障排除;

用户请求可能会在责任链的中间被拦截,最终可能不会被实际执行。这既是优点也是缺点,我们可以把它作为正确的控制拦截器。

标签: 责任