概述
某个请求需要多个对象进行处理,从而避免请求的发送者和接收之间的耦合关系。将这些对象连成一条链子,并沿着这条链子传递该请求,直到有对象处理它为止。
涉及角色
- Handler
抽象处理者角色:定义出一个处理请求的接口。通常由一个Java抽象类或者Java接口实现。 - ConcreteHandler
具体处理者角色:具体处理者接受到请求后,可以选择将该请求处理掉,或者将请求传给下一个处理者。因此,每个具体处理者需要保存下一个处理者的引用,以便把请求传递下去
UML
使用场景
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态指定一组对象处理请求
优点
- 降低耦合度。它将请求的发送者和接收者解耦。
- 简化了对象。使得对象不需要知道链的结构。
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
- 增加新的请求处理类很方便。
缺点
- 不能保证请求一定被接收。
- 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
- 可能不容易观察运行时的特征,有碍于除错
代码示例
报销审批流程是一个很好的例子,超过多少金额需要哪个级别的审批,比如加班交通费报销,不超过3k需要leader和经理审批,超过3k需要总监再次审批才能报销……
定义处理请求的方法
package com.designpattern.responsibility;
public interface Handler {
//处理请求的方法
public void handleRequest();
}
定义抽象处理者角色
package com.designpattern.responsibility;
public abstract class AbstractHandler {
//持有后继的责任对象
private Handler handler;
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
}
定义具体处理者角色。继承抽象类并实现具体的处理请求的方法
package com.designpattern.responsibility;
//核心类,实例化后生成一系列相互持有的对象,构成一条链
public class ConcreteHandler extends AbstractHandler implements Handler {
private String role;
//为方便演示,这里的构造函数传入参数标识代替多个具体类
public ConcreteHandler(String role) {
this.role = role;
}
//覆写具体处理请求的方法
@Override
public void handleRequest() {
System.out.println(role+" 审批!");
if(getHandler()!=null){
getHandler().handleRequest();
}
}
}
package com.designpattern.responsibility;
public class TestMain {
public static void main(String[] args) {
ConcreteHandler leader = new ConcreteHandler("直接领导");
ConcreteHandler manager = new ConcreteHandler("经理");
ConcreteHandler chief = new ConcreteHandler("总监");
ConcreteHandler accountant = new ConcreteHandler("财务");
double fee= Math.random()*9999;
System.err.println("加班费:"+fee);
if (fee<=3000) {
leader.setHandler(manager);
manager.setHandler(accountant);
} else {
leader.setHandler(manager);
manager.setHandler(chief);
chief.setHandler(accountant);
}
leader.handleRequest("加班交通费报销:");
}
}
运行结果:
加班费:3139.0867555809655
加班交通费报销: 直接领导 审批!
加班交通费报销: 经理 审批!
加班交通费报销: 总监 审批!
加班交通费报销: 财务 审批!
加班费:1624.8882151886996
加班交通费报销: 直接领导 审批!
加班交通费报销: 经理 审批!
加班交通费报销: 财务 审批!
逻辑非常简单:只要有下家,就传给下家处理;如果没有下家,就自行处理。