1.责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
2.结构图:
执行流程图:
参考:https://blog.csdn.net/u012810020/article/details/71194853
3.先看一个字符串过滤的例子:
3.1定义请求和响应类:
public class Request {
String requestStr;
public String getRequest() {
return requestStr;
}
public void setRequest(String request) {
this.requestStr = request;
}
}
public class Response {
String responseStr;
public String getResponse() {
return responseStr;
}
public void setResponse(String response) {
this.responseStr = response;
}
}
3.2再定义一个过滤的接口filter
public interface Filter {
void doFilter(Request request,Response response,FilterChain chain);
}
3.3FilterChain是一个实现了filter接口的链条对象
//过滤链条
public class FilterChain implements Filter{
//用List集合来存储过滤规则
List<Filter> filters = new ArrayList<>();
//用于标记规则的引用顺序
int index=0;
//往规则链条中添加规则
public FilterChain addFilter(Filter f) {
filters.add(f);
//代码的设计技巧:Chain链添加过滤规则结束后返回添加后的Chain,方便我们下面doFilter函数的操作
return this;
}
public void doFilter(Request request,Response response,FilterChain chain){
//index初始化为0,filters.size()为3,不会执行return操作
if(index==filters.size()){
return;
}
//每添加一个过滤规则,index自增1
Filter f=filters.get(index);
index++;
//根据索引值获取对应的规律规则对字符串进行处理
f.doFilter(request, response, chain);
}
}
它里面维护了一个list列表;专门用来存储各种过滤器;然后从list中取出过滤器并调用他们的过滤方法来实现不同的过滤业务。
3.4定义三个不同的过滤器,他们也实现了filter接口;并实现真正的过滤业务
//处理字符串中的HTML标记
public class HTMLFilter implements Filter {
public void doFilter(Request request, Response response,FilterChain chain) {
//将字符串中出现的"<>"符号替换成"[]"
System.out.println("初始requestStr:"+request.requestStr);
request.requestStr = request.requestStr
.replace('<', '[').replace('>', ']')+
//后面添加的是便于我们观察代码执行步骤的字符串
"----HTMLFilter()";
System.out.println("requestStr:"+request.requestStr);
chain.doFilter(request, response, chain);
response.responseStr += "---HTMLFilter()";
System.out.println("responseStr:"+response.responseStr);
}
}
//定义的过滤敏感字眼的过滤规则
public class SensitiveFilter implements Filter{
public void doFilter(Request request, Response response,FilterChain chain) {
//处理字符串中的敏感信息,将被就业和谐成就业
request.requestStr=request.requestStr
.replace("被就业", "就业").replace("敏感", "哈哈")+
//后面添加的是便于我们观察代码执行步骤的字符串
" ---sensitiveFilter()";
System.out.println("requestStr:"+request.requestStr);
chain.doFilter(request, response, chain);
response.responseStr+="---sensitiveFilter()";
System.out.println("responseStr:"+response.responseStr);
}
}
//定义FaceFilter
public class FaceFilter implements Filter {
public void doFilter(Request request, Response response, FilterChain chain) {
//将字符串中出现的":):"转换成"^V^";
request.requestStr = request.requestStr.replace(":):", "^V^")
//后面添加的是便于我们观察代码执行步骤的字符串
+ "----FaceFilter()";
System.out.println("requestStr:"+request.requestStr);
chain.doFilter(request, response, chain);
response.responseStr += "---FaceFilter()";
System.out.println("responseStr:"+response.responseStr);
}
}
3.5调用
public static void main(String args[]) {
//设定过滤规则,对msg字符串进行过滤处理
String msg = ":):,<script>,敏感,被就业,网络授课";
//过滤请求
Request request=new Request();
//set方法,将待处理字符串传递进去
request.setRequest(msg);
//处理过程结束,给出的响应
Response response=new Response();
//设置响应信息
response.setResponse("");
//FilterChain,过滤规则形成的拦截链条
FilterChain fc=new FilterChain();
//规则链条添加过滤规则,采用的是链式调用
fc.addFilter(new HTMLFilter())
.addFilter(new SensitiveFilter())
.addFilter(new FaceFilter());
//按照FilterChain的规则顺序,依次应用过滤规则
fc.doFilter(request, response, fc);
//打印请求信息
System.out.println("最终:"+request.getRequest());
//打印响应信息
System.out.println("最终:"+response.getResponse());
}
看一下打印结果:
可以看到,请求时,是按照----HTMLFilter() ---sensitiveFilter()----FaceFilter()来执行的;返回结果是按照倒叙执行的;主要是因为返回结果的打印语句是在调用了chain.doFilter(request, response, chain)之后。
其实这就是双向责任链的简单使用;OKHttp的底层就是使用了这种责任链的方式;可以在网络请求之前、之后分别做一些自己想做的事情。
4.单向的责任链
4.1定义过滤器的抽象类
public abstract class Filter {
private Filter nextFilter;
public void setFilter(Filter nextFilter) {
this.nextFilter = nextFilter;
}
public String doFilter(String str){
//首先调用自己的过滤方法
String result = handle(str);
//如果有下一过滤条件,继续调用;
if (nextFilter != null){
return nextFilter.doFilter(result);
}else {
return result;
}
}
abstract String handle(String str);
}
类中在doFilter方法中,首先调用了自己的handle方法,这是一个抽象方法,由具体子类实现;然后判断有没有给自己设置下一个过滤器;如果有,就调用下一个过滤器的过滤方法。
4.2看一下三个过滤器
public class HTMLFilter extends Filter {
@Override
String handle(String str) {
//将字符串中出现的"<>"符号替换成"[]"
System.out.println("初始str:"+str);
str = str.replace('<', '[').replace('>', ']')+
//后面添加的是便于我们观察代码执行步骤的字符串
"----HTMLFilter()";
System.out.println("str:"+str);
return str;
}
}
public class SensitiveFilter extends Filter {
@Override
String handle(String str) {
//处理字符串中的敏感信息,将被就业和谐成就业
str=str.replace("被就业", "就业").replace("敏感", "哈哈")+
//后面添加的是便于我们观察代码执行步骤的字符串
" ---sensitiveFilter()";
System.out.println("str:"+str);
return str;
}
}
public class FaceFilter extends Filter {
@Override
String handle(String str) {
//将字符串中出现的":):"转换成"^V^";
str = str.replace(":):", "^V^")
//后面添加的是便于我们观察代码执行步骤的字符串
+ "----FaceFilter()";
System.out.println("str:"+str);
return str;
}
}
它们的逻辑非常简单,只专注于处理自己的过滤逻辑即可;
4.3调用:
public static void main(String[] args) {
Filter htmlFilter = new HTMLFilter();
Filter sensitiveFilter = new SensitiveFilter();
Filter faceFilter = new FaceFilter();
htmlFilter.setFilter(sensitiveFilter);
sensitiveFilter.setFilter(faceFilter);
String msg = ":):,<script>,敏感,被就业,网络授课";
String result = htmlFilter.doFilter(msg);
System.out.println("result:"+result);
}
把三个过滤器对象实例化;然后,把第二个设置给第一个,把第三个设置给第二个;这样就组成了一个链条;只需要调用第一个的dofilter方法即可;
看看结果:
和上面的双向链是一样的;
5.优缺点及使用场景
优点
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。
缺点:
1、不能保证请求一定被接收。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
3、可能不容易观察运行时的特征,有碍于除错。
使用场景:
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。
参考:https://www.jianshu.com/p/8f89120f030c