职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
适用场景:
1、有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
3、处理一个请求的对象集合应被动态指定。
通用类图:
在大学里面当班干部,时常要向上级申请各方面的东西。譬如申请全班外出秋游,普通同学将申请表交给班长,班长签字之后交给辅导员,辅导员批准之后上交到主任办公室…就是这样,一个请求(这里是一份申请表)有时候需要经过好几个级别的处理者(这里是辅导员、主任)的审查才能够最终被确定可行与否。
在这里表现出来的是一个职责链,即不同的处理者对同一个请求可能担负着不同的处理方式、权限,但是我们希望这个请求必须到达最终拍板的处理者(否则秋游就没戏了)。这种关系就很适合使用职责链模式了。
类图结构如下:
代码实现如下:
// 全局变量,接口类型
/**
* 使用Java中的interface定义全局变量,可根据具体需要在
* 具体的包中使用静态导入相关的全局变量,语法如下:
* import static package01.package02.*;
*/
interfaceLevels {
publicstaticfinalintLEVEL_01 =1;
publicstaticfinalintLEVEL_02 =2;
publicstaticfinalintLEVEL_03 =3;
}
// 抽象请求类
abstractclassAbstractRequest {
privateString content =null;
publicAbstractRequest(String content) {
this.content = content;
}
publicString getContent() {
returnthis.content;
}
// 获得请求的级别
publicabstractintgetRequestLevel();
}
// 具体请求类01
classRequest01extendsAbstractRequest {
publicRequest01(String content) {
super(content);
}
@Override
publicintgetRequestLevel() {
returnLevels.LEVEL_01;
}
}
// 具体请求类02
classRequest02extendsAbstractRequest {
publicRequest02(String content) {
super(content);
}
@Override
publicintgetRequestLevel() {
returnLevels.LEVEL_02;
}
}
// 具体请求类03
classRequest03extendsAbstractRequest {
publicRequest03(String content) {
super(content);
}
@Override
publicintgetRequestLevel() {
returnLevels.LEVEL_03;
}
}
// 抽象处理者类,
abstractclassAbstractHandler {
// 责任链的下一个节点,即处理者
privateAbstractHandler nextHandler =null;
// 捕获具体请求并进行处理,或是将请求传递到责任链的下一级别
publicfinalvoidhandleRequest(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("职责链上的所有处理者都不能胜任该请求...");
}
}
}
// 设置责任链中的下一个处理者
publicvoidsetNextHandler(AbstractHandler nextHandler) {
this.nextHandler = nextHandler;
}
// 获取当前处理者的级别
protectedabstractintgetHandlerLevel();
// 定义链中每个处理者具体的处理方式
protectedabstractvoidhandle(AbstractRequest request);
}
// 具体处理者-01
classHandler01extendsAbstractHandler {
@Override
protectedintgetHandlerLevel() {
returnLevels.LEVEL_01;
}
@Override
protectedvoidhandle(AbstractRequest request) {
System.out.println("处理者-01 处理 "+ request.getContent() +"\n");
}
}
// 具体处理者-02
classHandler02extendsAbstractHandler {
@Override
protectedintgetHandlerLevel() {
returnLevels.LEVEL_02;
}
@Override
protectedvoidhandle(AbstractRequest request) {
System.out.println("处理者-02 处理 "+ request.getContent()+"\n");
}
}
// 具体处理者-03
classHandler03extendsAbstractHandler {
@Override
protectedintgetHandlerLevel() {
returnLevels.LEVEL_03;
}
@Override
protectedvoidhandle(AbstractRequest request) {
System.out.println("处理者-03 处理 "+ request.getContent()+"\n");
}
}
// 测试类
publicclassClient {
publicstaticvoidmain(String[] args) {
// 创建指责链的所有节点
AbstractHandler handler01 =newHandler01();
AbstractHandler handler02 =newHandler02();
AbstractHandler handler03 =newHandler03();
// 进行链的组装,即头尾相连,一层套一层
handler01.setNextHandler(handler02);
handler02.setNextHandler(handler03);
// 创建请求并提交到指责链中进行处理
AbstractRequest request01 =newRequest01("请求-01");
AbstractRequest request02 =newRequest02("请求-02");
AbstractRequest request03 =newRequest03("请求-03");
// 每次提交都是从链头开始遍历
handler01.handleRequest(request01);
handler01.handleRequest(request02);
handler01.handleRequest(request03);
}
}
测试结果:
处理者-01处理 请求-01
当前 处理者-01不足以处理 请求-02
处理者-02处理 请求-02
当前 处理者-01不足以处理 请求-03
当前 处理者-02不足以处理 请求-03
处理者-03处理 请求-03
在上面抽象处理者 AbstractHandler 类的 handleRequest() 方法中,被 protected 修饰,并且该方法中调用了两个必须被子类覆盖实现的抽象方法,这里是使用了模板方法模式(Template Mehtod)。其实在这里,抽象父类的 handleRequest() 具备了请求传递的功能,即对某些请求不能处理时,马上提交到下一结点(处理者)中,而每个具体的处理者仅仅完成了具体的处理逻辑,其他的都不用理。
记得第一次看到职责链模式的时候,我很惊讶于它能够把我们平时在代码中的 if..else.. 的语句块变成这样灵活、适应变化。例如:如果现在辅导员请长假了,但我们的秋游还是要争取申请成功呀,那么我们在 Client 类中可以不要创建 handler02,即不要将该处理者组装到职责链中。这样子处理比 if..else..好多了。或者说,突然来了个爱管闲事的领导,那么我照样可以将其组装到职责链中。
关于上面使用场景中提到的3个点:
1、处理者在运行时动态确定其实是我们在 Client 中组装的链所引起的,因为具体的职责逻辑就在链中一一对应起来;
2、因为不确定请求的具体处理者是谁,所以我们把所有可能的处理者组装成一条链,在遍历的过程中就相当于向每个处理者都提交了这个请求,等待其审查。并且在审查过程中,即使不是最终处理者,也可以进行一些请求的“包装”操作(这种功能类似于装饰者模式),例如上面例子中的签名批准;
3、处理者集合的动态指定跟上面的第1、2点类似,即在 Client 类中创建了所有可能的处理者。
不足之处:
1、对于每一个请求都需要遍历职责链,性能是个问题;
2、抽象处理者 AbstractHandler 类中的 handleRequest() 方法中使用了递归,栈空间的大小也是个问题。
个人看法:
职责链模式对于请求的处理是不知道最终处理者是谁,所以是运行动态寻找并指定;而命令模式中对于命令的处理时在创建命令是已经显式或隐式绑定了接收者。
相关文章: