责任链模式的定义
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。
标准的责任链模式,个人总结下来有如下几个特点:
- 链上的每个对象都有机会处理请求
- 链上的每个对象都持有下一个要处理对象的引用
- 链上的某个对象无法处理当前请求,那么它会把相同的请求传给下一个对象
用一张图表示以下使用了责任链模式之后的架构:
也就是说,责任链模式满足了请求发送者与请求处理者之间的松耦合,抽象非核心的部分,以链式调用的方式对请求对象进行处理。
责任链模式的优点及使用场景
- 实现了请求发送者与请求处理者之间的松耦合
- 可动态添加责任对象、删除责任对象、改变责任对象顺序,非常灵活
- 每个责任对象专注于做自己的事情,职责明确
什么时候需要用责任链模式?
系统设计的时候,注意区分主次就好,即哪部分是核心流程,哪部分是辅助流程,辅助流程是否有N多if...if...if...的场景,如果是且每个if都有一个统一的抽象,那么抽象辅助流程,把每个if作为一个责任对象进行链式调用,优雅实现,易复用可扩展。
首先还是抽象一个Filter:
public interface StudyPrepareFilter {
public void doFilter(PreparationList preparationList, FilterChain filterChain);
}
注意这里多了一个FilterChain,也就是责任链,是用于串起所有的责任对象的,它也是StudyPrepareFilter的一个子类:
public class FilterChain implements StudyPrepareFilter {
private int pos = 0;
private Study study;
private List<StudyPrepareFilter> studyPrepareFilterList;
public FilterChain(Study study) {
this.study = study;
}
public void addFilter(StudyPrepareFilter studyPrepareFilter) {
if (studyPrepareFilterList == null) {
studyPrepareFilterList = new ArrayList<StudyPrepareFilter>();
}
studyPrepareFilterList.add(studyPrepareFilter);
}
@Override
public void doFilter(PreparationList thingList, FilterChain filterChain) {
// 所有过滤器执行完毕
if (pos == studyPrepareFilterList.size()) {
study.study();
}
studyPrepareFilterList.get(pos++).doFilter(thingList, filterChain);
}
}
即这里有一个计数器,假设所有的StudyPrepareFilter没有调用完毕,那么调用下一个,否则执行Study的study()方法,即责任链调用完毕。
洗头
public class WashHairFilter implements StudyPrepareFilter {
@Override
public void doFilter(PreparationList preparationList, FilterChain filterChain) {
if (preparationList.isWashHair()) {
System.out.println("洗完头发");
}
filterChain.doFilter(preparationList, filterChain);
}
}
//洗脸
public class WashFaceFilter implements StudyPrepareFilter {
@Override
public void doFilter(PreparationList preparationList, FilterChain filterChain) {
if (preparationList.isWashFace()) {
System.out.println("洗完脸");
}
filterChain.doFilter(preparationList, filterChain);
}
}
//吃饭
public class HaveBreakfastFilter implements StudyPrepareFilter {
@Override
public void doFilter(PreparationList preparationList, FilterChain filterChain) {
if (preparationList.isHaveBreakfast()) {
System.out.println("吃完早饭");
}
filterChain.doFilter(preparationList, filterChain);
}
}
调用方法
@Test
public void testResponsibilityAdvance() {
PreparationList preparationList = new PreparationList();
preparationList.setWashFace(true);
preparationList.setWashHair(false);
preparationList.setHaveBreakfast(true);
Study study = new Study();
StudyPrepareFilter washFaceFilter = new WashFaceFilter();
StudyPrepareFilter washHairFilter = new WashHairFilter();
StudyPrepareFilter haveBreakfastFilter = new HaveBreakfastFilter();
FilterChain filterChain = new FilterChain(study);
filterChain.addFilter(washFaceFilter);
filterChain.addFilter(washHairFilter);
filterChain.addFilter(haveBreakfastFilter);
filterChain.doFilter(preparationList, filterChain);
}
有的人可能会问,你这个增加、减少责任对象,testResponsibilityAdvance()方法,不是还得addFilter,或者删除一行吗?我们回想一下,Servlet我们增加或减少Filter需要改动什么代码吗?不用,我们需要改动的只是web.xml而已。同样的道理,FilterChain里面有studyPrepareFilterList,我们完全可以把FilterChain做成一个Spring Bean,所有的Filter具体实现类也都是Spring Bean,注入studyPrepareFilterList就好了,伪代码为:
<bean id="filterChain" class="xxx.xxx.xxx.FilterChain">
<property name="studyPrepareFilterList">
<list>
<ref bean="washFaceFilter" />
<ref bean="washHairFilter" />
<ref bean="haveBreakfastFilter" />
</list>
</property>
</bean>
可以反转顺序执行的责任链
下面的代码是一个责任链实现方式,类似于servlet里面的filter实现。对于request和response的顺序做了反转。即:request是123的执行顺序,response是321的执行顺序。
/**
* 责任链模式
*/
public class Filter_Test {
public static void main(String[] a) {
Request request = new Request();
request.str = "大家好,<script> 这是敏感词";
Response response = new Response();
response.str="response";
FilterChain filterChain = new FilterChain();
filterChain.add(new HTMLFilter()).add(new SensitiveFilter());
filterChain.doFilter(request, response);
System.out.println(request.str);
System.out.println(response.str);
}
}
interface Filter {
boolean doFilter(Request request, Response response, FilterChain filterChain);
}
class HTMLFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response, FilterChain chain) {
request.str = request.str.replace("<","[").replace(">","]")+ " HTMLFilter()";
chain.doFilter(request, response);
response.str+="--HTMLFilter()";
return true;
}
}
class SensitiveFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response, FilterChain chain) {
request.str = request.str.replace("敏感词","非敏感词")+ " sensitiveFilter()";
chain.doFilter(request, response);
response.str+="--sensitiveFilter()";
return true;
}
}
class Request {
String str;
}
class Response {
String str;
}
class FilterChain {
List<Filter> filters = new ArrayList<>();
int pos = 0;
public FilterChain add(Filter filter) {
filters.add(filter);
return this;
}
public boolean doFilter(Request request, Response response) {
if(pos == filters.size()) {
return false;
}
Filter filter = filters.get(pos++);
return filter.doFilter(request, response, this);
}
}
参考链接:
参考链接
网友评论