责任链(Chain of Resposibility) 模式
概念
责任链(chain of Resposibility) 模式:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者 通过前一对象记住其下一个对象的引用而连成一条链
;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它位置。属于对象行为型模式。
-
抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
-
具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将请求转给他的后继者。
-
客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,他不关心处理细节和请求的传递过程。
代码
需求1:a1 -> a2 -> a3
实现先a1处理完交给a2,a2处理完再交给a3的逻辑,即: a1 -> a2 -> a3
public class Teacher {
private String name;
public Teacher(String name) {
this.name = name;
}
// 下一个处理的老师;1、链条的引用点
private Teacher next;
public Teacher getNext() {
return next;
}
public void setNext(Teacher next) {
this.next = next;
}
void handlerRequest() {
System.out.println(this + "正在处理。。。。。。。。");
// 2、下一个继续
if (next != null) {
next.handlerRequest();
}
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
'}';
}
}
public class MainTest {
public static void main(String[] args) {
Teacher a1 = new Teacher("a1");
Teacher a2 = new Teacher("a2");
Teacher a3 = new Teacher("a3");
// 3、构造链条
// a1->a2->a2
a1.setNext(a2);
a2.setNext(a3);
a1.handlerRequest();
}
}
测试结果:
Teacher{name='a1'}正在处理。。。。。。。。
Teacher{name='a2'}正在处理。。。。。。。。
Teacher{name='a3'}正在处理。。。。。。。。
需求2:1->2->3->本人->3->2->1
这个也就是我们学习过的Filter了
代码实现:
① Filter 接口
public interface Filter {
void doFilter(Request request,Response response,FilterChain chain);
}
@Data
public class Request {
// 请求内容
String msg;
public Request(String msg) {
this.msg = msg;
}
}
@Data
public class Response {
// 响应内容
private String content;
public Response(String content) {
this.content = content;
}
}
② Filter 的三个实现类
public class HttpFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
// 第一个filter的功能
request.msg += ">>>";
System.out.println("HttpFilter ... doFilter之前");
// 放行
chain.doFilter(request, response, chain);
System.out.println("HttpFilter ... doFilter之后");
}
}
public class CharacterFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
// 功能
request.msg += "====";
System.out.println("CharacterFilter ... doFilter之前");
// 放行
chain.doFilter(request, response, chain);
System.out.println("CharacterFilter ... doFilter之后");
}
}
public class EncodingFilter implements Filter {
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
// 功能
request.msg += "oooo";
System.out.println("EncodingFilter ... doFilter之前");
// 放行
chain.doFilter(request, response, chain);
System.out.println("EncodingFilter ... doFilter之后");
}
}
③ 我们的目标方法
public class My {
void hello() {
System.out.println("调用my.hello()方法");
}
}
```![在这里插入图片描述](https://img-blog.csdnimg.cn/7b173906028e45c7926d7b944096d929.png)
④ 维护链条
```java
/**
* 靠他维护链条
* handlerExecutionChain
*
* @author zhuicat
* @since 2023/8/13 8:19
*/
public class FilterChain implements Filter {
// 游标:记录当前执行的步骤
int cursor;
// Filter 的链
List<Filter> filterChain = new ArrayList<>();
// 最终要执行的目标方法
My target;
// 添加 filter 方法
void addFilter(Filter filter) {
filterChain.add(filter);
}
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
// 执行第一个 filter ,一次往下
// 游标小于总数量filter一直往下获取执行
if (cursor < filterChain.size()) {
Filter filter = filterChain.get(cursor);
cursor++;
// 执行 filter
filter.doFilter(request, response, chain);
} else {
// filter执行完了,需要执行目标方法了
target.hello();
}
}
public My getTarget() {
return target;
}
public void setTarget(My target) {
this.target = target;
}
}
⑤ 主方法
public class MainTest {
public static void main(String[] args) {
FilterChain chain = new FilterChain();
// web.xml
HttpFilter httpFilter = new HttpFilter();
CharacterFilter characterFilter = new CharacterFilter();
EncodingFilter encodingFilter = new EncodingFilter();
chain.addFilter(httpFilter);
chain.addFilter(characterFilter);
chain.addFilter(encodingFilter);
chain.setTarget(new My());
// filter 如何链式执行
chain.doFilter(new Request("hello,world"), new Response("dddddddddddddddddd"), chain);
}
}
⑥ 执行结果
HttpFilter ... doFilter之前
CharacterFilter ... doFilter之前
EncodingFilter ... doFilter之前
调用my.hello()方法
EncodingFilter ... doFilter之后
CharacterFilter ... doFilter之后
HttpFilter ... doFilter之后
完成上述需求