有一天,你有事想要请个长假,找到项目经理;项目经理说只能批2天的假,他去找部门经理;部门经理只能批5天的假,他去找人事部经理;最终人事部经理决定是否准假。这就是一个链式关系。
职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
首先还是看看结构类图如下
上图中包括:
1、抽象处理者角色(Handler:Approver):定义一个处理请求的接口,和一个后继连接(可选)
2、具体处理者角色(ConcreteHandler:President):处理它所负责的请求,可以访问后继者,如果可以处理请求则处理,否则将该请求转给他的后继者。
3、客户类(Client):向一个链上的具体处理者ConcreteHandler对象提交请求。
回答一开始的例子。请假时有三种权限的handler,分别是项目经理、部门经理、人事经理分别对应着2天、5天、5天以上的权限。
首先是抽象处理角色:
/*
* 抽象处理者类
*
*/
public abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler){
this.nextHandler = nextHandler;
}
public abstract void handleRequest(int request);
}
三个具体处理角色类:
/*
* 具体职责处理者A:项目经理长角色
*
*/
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(int leaveDay) {
if(leaveDay <= 2){
// 满足处理条件 处理请求
System.out.println("请假天数小于3天 由项目组长审批");
} else {
nextHandler.handleRequest(leaveDay);
}
}
}
/*
* 具体职责处理者B: 部门经理角色
*
*/
public class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(int leaveDay) {
if(2 < leaveDay && leaveDay <= 5){
// 满足处理条件 处理请求
System.out.println("请假天数大于2天且小于等于5天 由部门经理审批");
} else {
nextHandler.handleRequest(leaveDay);
}
}
}
/*
* 具体职责处理者C:人事经理角色
*
*/
public class ConcreteHandlerC extends Handler {
@Override
public void handleRequest(int leaveDay) {
if(leaveDay > 5){
System.out.println("当请假天数大于5天的情况下 由人事经理审批");
}
}
}
最后是客户端类
/*
* 客户端类
* 负责创建职责链和发送请求
* 当职责链(职责的传递顺序/请求的处理顺序)建好之后,客户端只负责将请求发送出去,
* 而具体请求在职责链上的传递和最终由链上的哪个对象进行处理不由客户端关心
*
*/
public class Client {
public static void main(String[] args) {
Handler handlerA,handlerB,handlerC;
handlerA = new ConcreteHandlerA();
handlerB = new ConcreteHandlerB();
handlerC = new ConcreteHandlerC();
// 创建职责链 handlerA ——> handlerB ——> handlerC
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
// 发送请假请求一
handlerA.handleRequest(1);
// 发送请假请求二
handlerA.handleRequest(7);
// 发送请假请求二
handlerA.handleRequest(3);
}
}
结果显示为
任何设计模式都有其优缺点:
优点:
1、降低耦合度 :该模式使得一个对象无需知道是其他哪一个对象处理其请求。对象仅需知道该请求会被“正确”地处理。接收者和发送者都没有对方的明确的信息,且链中的对象不需知道链的结构。
2、职责链可简化对象的相互连接 : 结果是,职责链可简化对象的相互连接。它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。
3、增强了给对象指派职责的灵活性。
4、增加新的请求处理类很方便。
缺点:
1、不能保证请求一定被接收。既然一个请求没有明确的接收者,那么就不能保证它一定会被处理 —该请求可能一直到链的末端都得不到处理。一个请求也可能因该链没有被正确配置而得不到处理。。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便;可能会造成循环调用。
总结:在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。