前言
责任链模式属于行为型设计模式,所谓责任链,就是把责任处理对象连成一条链,这样当一个处理对象不能及时处理的时候就会交给下一个处理对象处理,直到被处理为止。就像我们找人签字盖章的时候,当一个对象不能处理的时候他会告诉你你应该下一个部门进行盖章,而如果下一个部门仍然不能处理就会继续告诉你下一个应该去的部门,直到把章盖好。这个例子不一定恰当,但是反映了责任传递这么一个过程。责任传递是责任链模式的核心,责任链模式使得多个处理对象有机会处理请求,从而避免请求发送者与请求接收者之间的解耦,把这些对象连成一条链,并把请求沿着这条链进行传递,直到完成请求的处理。请求发送者并不需要哪一个对象处理这个请求,因为总有一个请求接收者进行处理。在责任链模式中,由于请求的处理对象要形成一条链,所以每一个处理对象都要保存下一个处理对象的引用,这点与数据结构中的链表很相似。
问题背景
假设小张需要申请加薪,于是他首先向部门经理申请,部门经理觉得这个他做不了主于是又汇报给总监,总监觉得他也做不了主,于是就汇报给总经理,总经理觉得小张的表现很不错,遂同意小张的加薪申请。
那么就根据责任链模式进行编码
package default;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DutyChainMode{
//管理人员抽象类
public abstract class Manager{
protected String name;
protected Manager superior;
public Manager(String name,Manager superior){
this(name);
this.superior = superior;
}
public Manager(String name){this.name = name;}
public void setName(String name){this.name = name;}
public String getName(){return name;}
public void setSuperior(Manager superior){this.superior = superior;}
public Manager getSuperior(){return superior;}
public abstract void handleApplicationRequest(String content,double limit);
public abstract String getHanldeObject();
}
//部门经理
public class DepartmentManager extends Manager{
public DepartmentManager(String name){super(name);}
public void handleApplicationRequest(String content,double limit){
if(content.equals("加薪")){
superior.handleApplicationRequest(content,limit);
}
}
public String getHanldeObject(){
return "部门经理";
}
}
//总监
public class Majordomo extends Manager{
public Majordomo(String name){super(name);}
public void handleApplicationRequest(String content,double limit){
if(content.equals("加薪") && Math.floor(limit) < 100){
System.out.println(getHanldeObject() + "已经加薪申请。处理时间" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
}else if(content.equals("加薪") && Math.floor(limit) > 100){
superior.handleApplicationRequest(content,limit);
}
}
public String getHanldeObject(){
return "总监";
}
}
//总经理
public class GeneralManager extends Manager{
public GeneralManager(String name){super(name);}
public void handleApplicationRequest(String content,double limit){
if(content.equals("加薪")){
System.out.println(getHanldeObject() + "已经加薪申请。处理时间" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
}
}
@Override
public String getHanldeObject() {
return "总经理";
}
}
//申请人
public class Applicant{
private String name;
private String content;
private Manager manager;
public Applicant(String name){this.name = name;}
public Applicant(String name,Manager manager){this(name);this.manager = manager;}
public void setName(String name){this.name = name;}
public String getName(){return name;}
public void setContent(String content){this.content = content;}
public String getContent(){return content;}
public void setManager(Manager manager){this.manager = manager;}
public Manager getManager(){return manager;}
public void submitApplicationRequest(String content,double limit){
manager.handleApplicationRequest(content,limit);
}
}
public static void main(String[] args){
DutyChainMode dm = new DutyChainMode();
Applicant xiaozhang = dm.new Applicant("小张");
Manager departmentManager = dm.new DepartmentManager("经理");
Manager majordomo = dm.new Majordomo("总监");
Manager genralManager = dm.new GeneralManager("总经理");
departmentManager.setSuperior(majordomo);
majordomo.setSuperior(genralManager);
xiaozhang.setManager(departmentManager);
xiaozhang.submitApplicationRequest("加薪", 400);
}
}
测试结果:
可以发现,Applicant对象仅仅是把加薪申请直接提交给他的直接上级,至于他的直接上级能否处理则不是他需要关心的了,对与申请人来说他只关心申请处理的结果,处理细节不需要关心。而处理细节是在Manager对象中进行定义的,通过设置上下级关系使得申请可以被逐级交给下一个处理对象进行处理,这也是责任链模式最吸引人的地方。当然模式总会有不足,比如,如果当申请提交到总经理那里的时候,总经理没有进行及时处理就会造成申请人的持续等待,这时我们不希望看到的。最后,我们再对责任链模式进行一个简单的总结:
- 发送者不需要知道接收者的具体信息,只要交给一个接收者就可以了。降低了客户与系统的耦合程度
- 对于每一个具体的处理对象来讲,它只需要保存其下一个处理对象的引用就可以了,这样就使得处理对象之间的耦合度降低
- 责任链的结构是在客户端定义的,这就使得可以随时增加或者修改责任链的结构,增强了指派责任的灵活性
- 如果请求到达责任链的末端仍然没有处理就会造成客户端的等待