一、责任链模式简介
责任链模式是对象的行为模式。使多个对象都有机会处理请求,从而避免请求的发送者和接受者直接的耦合关系。将这些对象连成一条链,沿着这条链传递该请求,直到有一个对象处理它为止。责任链模式强调的是每一个对象及其对下家的引用来组成一条链,利用这种方式将发送者和接收者解耦。
角色:
1、抽象处理者角色(Handler):
定义出一个处理请求的接口。如果需要,接口可以定义出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。
2、具体处理者角色(ConcreteHandler):
具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
模板示例:
1、抽象处理者角色
2、具体处理者角色
举这样一个例子,在玩具工厂的生产车间,流水线就是一条责任链,假如一个玩具飞机有外壳装配员,引擎装配员,螺旋桨装配员,模型包装员组成。当这个物件飞机流到谁那里,谁就负责安装他负责的这一部分,这部分安装完成后流到下一个环节,直到所有环境完成。这个是一个生产的责任链。还有一个质量检测链,质量检测也分多部,外壳检测,引擎检测,螺旋桨检测,包装检测。当产品留到检测员那里检测自己负责的那一块,如果有问题直接拎出来,如果没问题则传给下一个检测员,直到所有检测完成。这两个都是责任链,但是区别是,生成责任链每个人都会处理,并处理一部分;而质量检测责任链经过判断,要么处理掉,要么不处理流下去。这就是责任链的两种分类,后一种叫做纯的责任链,前一种叫做不纯的责任链,纯的责任链在实际应用中很少存在,常见的为不纯的责任链,上面的模型是模拟纯的责任链来处理的。
实际使用案例:
责任链模式在现实中使用的很多,常见的就是OA系统中的工作流。 在java中的实际应用有Servlet中的过滤器(Filter),Struts2的拦截器(Interceptor)。Struts2本身在Servlet中也是以Filter的形式出现的,所以Struts2的结构图中,也可以明显看出Filter和Interceptor这两条链的存在。
二、示例演示
1、定义请求级别的接口:
8、分析:
在上面抽象处理者 AbstractHandler 类的 handleRequest() 方法中,被 protected 修饰,并且该方法中调用了两个必须被子类覆盖实现的抽象方法,这里是使用了模板方法模式(Template Mehtod)。其实在这里,抽象父类的 handleRequest() 具备了请求传递的功能,即对某些请求不能处理时,马上提交到下一结点(处理者)中,而每个具体的处理者仅仅完成了具体的处理逻辑,其他的都不用理。
三、总结
1、处理者在运行时动态确定是我们在 Client 中组装的链所引起的,因为具体的职责逻辑就在链中一一对应起来;
2、因为不确定请求的具体处理者是谁,所以我们把所有可能的处理者组装成一条链,在遍历的过程中就相当于向每个处理者都提交了这个请求,等待其审查。并且在审查过程中,即使不是最终处理者,也可以进行一些请求的“包装”操作(这种功能类似于装饰者模式);
3、处理者集合的动态指定跟上面的第1、2点类似,即在 Client 类中创建了所有可能的处理者。
4、改变内部的传递规则
每个处理者都可以去动态地指定他的继任者。
5、可以从职责链任何一关开始。
6、用与不用的区别
不用职责链的结构,反映在代码上即使我们需要在一个类中去写上很多if….else语句。
如果用了职责链,相当于我们面对的是一个黑箱,我们只需要认识其中的一个处理者,然后让黑箱内部去负责传递就好了。
责任链模式是对象的行为模式。使多个对象都有机会处理请求,从而避免请求的发送者和接受者直接的耦合关系。将这些对象连成一条链,沿着这条链传递该请求,直到有一个对象处理它为止。责任链模式强调的是每一个对象及其对下家的引用来组成一条链,利用这种方式将发送者和接收者解耦。
角色:
1、抽象处理者角色(Handler):
定义出一个处理请求的接口。如果需要,接口可以定义出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。
2、具体处理者角色(ConcreteHandler):
具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
模板示例:
1、抽象处理者角色
public abstract class Handler {
/**
* 持有后继的责任对象
*/
protected Handler successor;
/**
* 示意处理请求的方法,传入一个参数
*/
public abstract void handlerRequest(String condition);
/**
* 取值方法
*/
public Handler getSuccessor() {
return successor;
}
/**
* 赋值方法,设置后继的责任对象
*/
public void setSuccessor(Handler successor) {
this.successor = successor;
}
}
2、具体处理者角色
public class ConcreteHandler1 extends Handler {
@Override
public void handlerRequest(String condition) {
// 如果是自己的责任,就自己处理,否则负责传给下家处理
if(condition.equals("ConcreteHandler1")){
System.out.println( "ConcreteHandler1 handled ");
return ;
}else{
System.out.println( "ConcreteHandler1 passed ");
getSuccessor().handlerRequest(condition);
}
}
}
public class ConcreteHandler2 extends Handler {
@Override
public void handlerRequest(String condition) {
// 如果是自己的责任,就自己处理,否则负责传给下家处理
if(condition.equals("ConcreteHandler2")){
System.out.println( "ConcreteHandler2 handled ");
return ;
}else{
System.out.println( "ConcreteHandler2 passed ");
getSuccessor().handlerRequest(condition);
}
}
}
public class ConcreteHandlerN extends Handler {
/**
* 这里假设n是链的最后一个节点必须处理掉。
* 在实际情况下,可能出现环,或者是树形,
* 这里并不一定是最后一个节点。
*
*/
@Override
public void handlerRequest(String condition) {
System.out.println( "ConcreteHandlerN handled");
}
}
3、测试方法
public class Client {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handlern = new ConcreteHandlerN();
//链起来handler1-->handler2-->handlern
handler1.setSuccessor(handler2);
handler2.setSuccessor(handlern);
//假设这个请求是ConcreteHandler2的责任
handler1.handlerRequest("ConcreteHandler2");
}
}
使用案例分析:
举这样一个例子,在玩具工厂的生产车间,流水线就是一条责任链,假如一个玩具飞机有外壳装配员,引擎装配员,螺旋桨装配员,模型包装员组成。当这个物件飞机流到谁那里,谁就负责安装他负责的这一部分,这部分安装完成后流到下一个环节,直到所有环境完成。这个是一个生产的责任链。还有一个质量检测链,质量检测也分多部,外壳检测,引擎检测,螺旋桨检测,包装检测。当产品留到检测员那里检测自己负责的那一块,如果有问题直接拎出来,如果没问题则传给下一个检测员,直到所有检测完成。这两个都是责任链,但是区别是,生成责任链每个人都会处理,并处理一部分;而质量检测责任链经过判断,要么处理掉,要么不处理流下去。这就是责任链的两种分类,后一种叫做纯的责任链,前一种叫做不纯的责任链,纯的责任链在实际应用中很少存在,常见的为不纯的责任链,上面的模型是模拟纯的责任链来处理的。
实际使用案例:
责任链模式在现实中使用的很多,常见的就是OA系统中的工作流。 在java中的实际应用有Servlet中的过滤器(Filter),Struts2的拦截器(Interceptor)。Struts2本身在Servlet中也是以Filter的形式出现的,所以Struts2的结构图中,也可以明显看出Filter和Interceptor这两条链的存在。
二、示例演示
1、定义请求级别的接口:
// 全局变量,接口类型
interface Levels {
public static final int LEVEL_01 = 1;
public static final int LEVEL_02 = 2;
public static final int LEVEL_03 = 3;
}
2、定义请求的抽象类
// 抽象请求类
abstract class AbstractRequest {
private String content = null;
public AbstractRequest(String content) {
this.content = content;
}
public String getContent() {
return this.content;
}
// 获得请求的级别
public abstract int getRequestLevel();
}
3、定义请求的具体实现
// 具体请求类01
class Request01 extends AbstractRequest {
public Request01(String content) {
super(content);
}
@Override
public int getRequestLevel() {
return Levels.LEVEL_01;
}
}
// 具体请求类02
class Request02 extends AbstractRequest {
public Request02(String content) {
super(content);
}
@Override
public int getRequestLevel() {
return Levels.LEVEL_02;
}
}
// 具体请求类03
class Request03 extends AbstractRequest {
public Request03(String content) {
super(content);
}
@Override
public int getRequestLevel() {
return Levels.LEVEL_03;
}
}
4、定义处理请求的抽象类
// 抽象处理者类,
abstract class AbstractHandler {
// 责任链的下一个节点,即处理者
private AbstractHandler nextHandler = null;
// 捕获具体请求并进行处理,或是将请求传递到责任链的下一级别
public final void handleRequest(AbstractRequest request) {
// 若该请求与当前处理者的级别层次相对应,则由自己进行处理
if (this.getHandlerLevel() == request.getRequestLevel()) {
this.handle(request);
} else {
// 当前处理者不能胜任,则传递至职责链的下一节点
if (this.nextHandler != null) {
System.out.println("当前 处理者-0" + this.getHandlerLevel()
+ " 不足以处理 请求-0" + request.getRequestLevel());
// 这里使用了递归调用
this.nextHandler.handleRequest(request);
} else {
System.out.println("职责链上的所有处理者都不能胜任该请求...");
}
}
}
// 设置责任链中的下一个处理者
public void setNextHandler(AbstractHandler nextHandler) {
this.nextHandler = nextHandler;
}
// 获取当前处理者的级别
protected abstract int getHandlerLevel();
// 定义链中每个处理者具体的处理方式
protected abstract void handle(AbstractRequest request);
}
5、实现具体的请求处理类
// 具体处理者-01
class Handler01 extends AbstractHandler {
@Override
protected int getHandlerLevel() {
return Levels.LEVEL_01;
}
@Override
protected void handle(AbstractRequest request) {
System.out.println("处理者-01 处理 " + request.getContent() + "\n");
}
}
// 具体处理者-02
class Handler02 extends AbstractHandler {
@Override
protected int getHandlerLevel() {
return Levels.LEVEL_02;
}
@Override
protected void handle(AbstractRequest request) {
System.out.println("处理者-02 处理 " + request.getContent()+ "\n");
}
}
// 具体处理者-03
class Handler03 extends AbstractHandler {
@Override
protected int getHandlerLevel() {
return Levels.LEVEL_03;
}
@Override
protected void handle(AbstractRequest request) {
System.out.println("处理者-03 处理 " + request.getContent()+ "\n");
}
}
6、测试类
// 测试类
public class Client {
public static void main(String[] args) {
// 创建指责链的所有节点
AbstractHandler handler01 = new Handler01();
AbstractHandler handler02 = new Handler02();
AbstractHandler handler03 = new Handler03();
// 进行链的组装,即头尾相连,一层套一层
handler01.setNextHandler(handler02);
handler02.setNextHandler(handler03);
// 创建请求并提交到指责链中进行处理
AbstractRequest request01 = new Request01("请求-01");
AbstractRequest request02 = new Request02("请求-02");
AbstractRequest request03 = new Request03("请求-03");
// 每次提交都是从链头开始遍历
handler01.handleRequest(request01);
handler01.handleRequest(request02);
handler01.handleRequest(request03);
}
}
7、结果:
处理者-01 处理 请求-01
当前 处理者-01 不足以处理 请求-02
处理者-02 处理 请求-02
当前 处理者-01 不足以处理 请求-03
当前 处理者-02 不足以处理 请求-03
处理者-03 处理 请求-03
8、分析:
在上面抽象处理者 AbstractHandler 类的 handleRequest() 方法中,被 protected 修饰,并且该方法中调用了两个必须被子类覆盖实现的抽象方法,这里是使用了模板方法模式(Template Mehtod)。其实在这里,抽象父类的 handleRequest() 具备了请求传递的功能,即对某些请求不能处理时,马上提交到下一结点(处理者)中,而每个具体的处理者仅仅完成了具体的处理逻辑,其他的都不用理。
三、总结
1、处理者在运行时动态确定是我们在 Client 中组装的链所引起的,因为具体的职责逻辑就在链中一一对应起来;
2、因为不确定请求的具体处理者是谁,所以我们把所有可能的处理者组装成一条链,在遍历的过程中就相当于向每个处理者都提交了这个请求,等待其审查。并且在审查过程中,即使不是最终处理者,也可以进行一些请求的“包装”操作(这种功能类似于装饰者模式);
3、处理者集合的动态指定跟上面的第1、2点类似,即在 Client 类中创建了所有可能的处理者。
4、改变内部的传递规则
每个处理者都可以去动态地指定他的继任者。
5、可以从职责链任何一关开始。
6、用与不用的区别
不用职责链的结构,反映在代码上即使我们需要在一个类中去写上很多if….else语句。
如果用了职责链,相当于我们面对的是一个黑箱,我们只需要认识其中的一个处理者,然后让黑箱内部去负责传递就好了。