责任链模式
一、责任链模式介绍
1、定义与类型
为请求创建一个接收此次请求对象的链
类型:行为型
2、适用场景
一个请求的处理需要多个对象当中的一个或几个协作处理
3、优点
请求的发送者和接收者(请求的处理)解耦
责任链可以动态组合
4、缺点
责任链太长或者处理时间过长,影响性能
责任链有可能过多
5、相关设计模式
责任链模式和状态模式
责任链模式中,各个对象并不指定下一个处理对象者是谁,只有客户端来设置顺序和元素,直到被某个责任链元素处理或者整个责任链结束。
状态模式是让每个状态对象知道下一个状态对象是谁,在编译时就设定好了。
二、代码示例
模拟场景:发布课程,课程中需要含有手记和视频,才能批准;
第一步,先检查手记,不为空才能批准,否则不批准
第二步,再检查视频,不为空才能批准,否则不批准
课程类:
public class Course {
private String name;
private String article;
private String video;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getArticle() {
return article;
}
public void setArticle(String article) {
this.article = article;
}
public String getVideo() {
return video;
}
public void setVideo(String video) {
this.video = video;
}
public Course(String name, String article, String video) {
this.name = name;
this.article = article;
this.video = video;
}
public Course() {
}
}
1、v1版本(Appover):
处理抽象类:
public abstract class Appover {
protected Appover nextAppover;
public void setNextAppover(Appover nextAppover){
this.nextAppover = nextAppover;
}
public abstract void deploy(Course course);
}
手记处理类:
public class ArticleAppover extends Appover {
@Override
public void deploy(Course course) {
if (StringUtil.isNotEmpty(course.getArticle())){
System.out.println(course.getName() + " 含有手记, 批准");
if (nextAppover != null){
nextAppover.deploy(course);
} else {
System.out.println("链条结束");
}
} else {
System.out.println(course.getName() + " 不包含有手记, 不批准,流程结束");
return;
}
}
}
视频处理类:
public class VideoAppover extends Appover {
@Override
public void deploy(Course course) {
if (StringUtil.isNotEmpty(course.getVideo())){
System.out.println(course.getName() + " 含有视频, 批准");
if (nextAppover!= null){
nextAppover.deploy(course);
} else {
System.out.println("链条结束");
}
} else {
System.out.println(course.getName() + " 不包含有视频, 不批准,流程结束");
return;
}
}
}
测试类:
public class Test {
public static void main(String[] args) {
Appover articleAppover = new ArticleAppover();
Appover videoAppover = new VideoAppover();
articleAppover.setNextAppover(videoAppover);
Course course1 = new Course("责任链模式讲解", "手记", "视频");
articleAppover.deploy(course1);
Course course2 = new Course();
course2.setName("设计模式");
articleAppover.deploy(course2);
}
}
输出:
责任链模式讲解 含有手记, 批准
责任链模式讲解 含有视频, 批准
链条结束
设计模式 不包含有手记, 不批准,流程结束
2、v2版本(Handler),(推荐,使用起来更加灵活):
处理抽象类:
public abstract class AbstractHandler {
abstract void doHandler(HandlerChainContext handlerChainContext, Course course); // handler方法
}
处理类上下文(对处理类进行包装):
/**
* handler上下文,主要负责维护链,和链的执行
*/
public class HandlerChainContext {
HandlerChainContext next; // 下一个节点
AbstractHandler handler;
public HandlerChainContext(AbstractHandler handler) {
this.handler = handler;
}
void handler(Course course) {
this.handler.doHandler(this, course);
}
/**
* 继续执行下一个
*/
void runNext(Course course) {
if (this.next != null) {
this.next.handler(course);
} else {
System.out.println("链条结束");
}
}
}
手记处理类:
public class ArticleHandler extends AbstractHandler{
@Override
void doHandler(HandlerChainContext handlerChainContext, Course course) {
if (StringUtil.isNotEmpty(course.getArticle())){
System.out.println(course.getName() + " 含有手记, 批准");
// 继续执行下一个
handlerChainContext.runNext(course);
} else {
System.out.println(course.getName() + " 不包含有手记, 不批准,流程结束");
return;
}
}
}
视频处理类:
public class VideoHandler extends AbstractHandler {
@Override
void doHandler(HandlerChainContext handlerChainContext, Course course) {
if (StringUtil.isNotEmpty(course.getVideo())){
System.out.println(course.getName() + " 含有视频, 批准");
// 继续执行下一个
handlerChainContext.runNext(course);
} else {
System.out.println(course.getName() + " 不包含有视频, 不批准,流程结束");
return;
}
}
}
链路类:
public class PipelineChain {
/**
* 初始化的时候造一个head,作为责任链的开始,但是并没有具体的处理
* 目的就是启动下一个handler
*/
public HandlerChainContext head = new HandlerChainContext(new AbstractHandler() {
@Override
void doHandler(HandlerChainContext handlerChainContext, Course course) {
handlerChainContext.runNext(course);
}
});
public void requestProcess(Course course) {
this.head.handler(course);
}
public void addLast(AbstractHandler handler) {
HandlerChainContext context = head;
while (context.next != null) {
context = context.next;
}
context.next = new HandlerChainContext(handler);
}
}
测试类:
public class Test {
public static void main(String[] args) {
PipelineChain pipelineChain = new PipelineChain();
// 优点:此处的 ArticleHandler 和 VideoHandler 不需要直接产生关联
// 即可以直接在中间增加其他 Handler
pipelineChain.addLast(new ArticleHandler());
pipelineChain.addLast(new VideoHandler());
Course course1 = new Course("责任链模式讲解", "手记", "视频");
// 发起请求
pipelineChain.requestProcess(course1);
Course course2 = new Course();
course2.setName("设计模式");
// 发起请求
pipelineChain.requestProcess(course2);
}
}
输出:
责任链模式讲解 含有手记, 批准
责任链模式讲解 含有视频, 批准
链条结束
设计模式 不包含有手记, 不批准,流程结束
三、源码示例
Servlet中的Filter