一、概述
避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。将接收请求的对象连接成一条链,并且沿着这条链传递请求,知道有一个对象能够处理它为止。
二、结构与实现
- 结构
(1)Handler(抽象处理者):
定义了一个抽象请求处理的方法,一般设计为抽象类。因每一个处理者的下家还是一个处理者,所以在抽象处理者中定义了一个抽象处理者类型的对象作为其下家的引用,通过该引用处理者可以连成一条链。
(2)ConcreteHandler(具体处理者):
抽象处理者子类,可以处理用户请求,处理请求之前进行判断,是否有相应的处理权限,如果可以处理请求就处理它,否则转发给后继者。
- 实现
abstract class Handler{
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler){
this.nextHandler=nextHandler;
}
public abstract void handleRequest(String request);
}
class ConcreteHandler extends Handler{
public abstract void handlerRequest(String request){
if(请求满足条件){
//处理请求
}else{
this.nextHandler.handlerRequest(request);//请求转发
}
}
}
三、应用案例
- 分析:
具体处理者:主任(5万以下)、副董事(5-10万)、董事长(10-50万)、董事会(50万以上)。
-
类图:
-
代码实现
//采购订单类
class Order{
private int id; //订单id
private double price; //订单金额
private String purpose; //目的
public Order(int id, double price, String purpose) {
this.id = id;
this.price = price;
this.purpose = purpose;
}
//setter和getter省略
}
//审批抽象类
abstract class Handler{
protected String name;
protected Handler nextHandler;
public Handler(String name){
this.name=name;
}
public void setNextHandler(Handler nextHandler){
this.nextHandler=nextHandler;
}
public abstract void handleRequest(Order order);
}
//主任审批者
class Director extends Handler{
public Director(String name){
super(name);
}
public void handlerRequest(Order order){
if(order.getPrice()<50000){
System.out.println("主任:"+this.name+"; 审批采购单:单号为"+order.getId()+"; 目的:"+order.getPurpose()
+"; 金额:"+order.getPrice());
}else{
System.out.println("金额过大,主任无法审批,转发中...");
nextHandler.handleRequest(order);
}
}
}
//副董事长
class VicePresident extends Handler{
public VicePresident(String name) {
super(name);
}
@Override
public void handleRequest(Order order) {
if(order.getPrice()<100000){
System.out.println("副董事长:"+this.name+"; 审批采购单:单号为"+order.getId()+"; 目的:"+order.getPurpose()
+"; 金额:"+order.getPrice());
}else {
System.out.println("金额过大,副董事长无法审批,转发中...");
nextHandler.handleRequest(order);
}
}
}
//董事长
class President extends Handler{
public President(String name) {
super(name);
}
@Override
public void handleRequest(Order order) {
if(order.getPrice()<500000){
System.out.println("董事长:"+this.name+"; 审批采购单:单号为"+order.getId()+"; 目的:"+order.getPurpose()
+"; 金额:"+order.getPrice());
}else {
System.out.println("金额过大,董事长无法审批,转发中...");
nextHandler.handleRequest(order);
}
}
}
//董事会
class Congress extends Handler{
public Congress(String name) {
super(name);
}
@Override
public void handleRequest(Order order) {
System.out.println("董事会:"+this.name+"; 审批采购单:单号为"+order.getId()+"; 目的:"+order.getPurpose()
+"; 金额:"+order.getPrice());
}
}
//客户端
public class client {
public static void main(String[] args) {
//创建各个审批者
Director director=new Director("jack");
VicePresident vicePresident=new VicePresident("harry");
President president=new President("boss");
Congress congress=new Congress("everyBoss");
//设置下家,组成一条链。主任->副董事长->董事长->董事会
director.setNextHandler(vicePresident);
vicePresident.setNextHandler(president);
president.setNextHandler(congress);
//创建采购订单
Order order=new Order(123,143,"购买公共设施");
//从主任开始进行审核
director.handleRequest(order);
}
}
四、纯责任链与不纯责任链
- 纯的责任链模式:
一个纯的责任链模式要求一个具体处理者对象只能在两个行为中选择一个,即要么进行处理,要么进行转发,不能出现某个请求未被任何一个处理者对象处理的情况。如上的应用案例就是纯的责任链模式。
- 不纯的责任链模式
一个不纯的责任链模式中允许某个请求被一个具体处理者部分处理后再向下传递,或者一个具体处理者处理完某个请求后其后继处理者可以继续处理该请求。而且,一个请求可以最终不被任何处理者对象所接收并处理。
五、总结
- 使用传统方式if…else if…else或switch来开发的话,客户端会根据不同的条件的进行处理,而当条件修改时,必然会修改到客户端的代码。此时,使用责任链模式可以很好地解决这问题。
- 责任链模式有两个角色。一是抽象处理者,在抽象处理者中又对自己进行了引用,方便设置其下家。二是具体处理者,通过判断,让具体处理者决定是处理该请求还是进行请求转发。
- 责任链的适用环境:有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定;在不明确指定接收者的情况下向多个对象中的一个提交一个请求;可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中处理者之间的先后次序。