责任链模式(Chain of Responsibility):
使多个对象有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 简而言之,就是为多个对象办理同一请求的时机,并且将他们组成一条链,请求过来,能够处理就处理,不能处理的传递给下一个对象,直到解决为止。
责任链模式结构:
具体处理者(ConcreteHander):处理它所负责的请求,可以访问它的后继者,如果可以处理该请求就处理,不能处理的,传递给他的后继者;
Client:向链上的具体请求处理者提交请求。
实例:在公司经常会出现员工请假,加薪等情况,而不同的事项可能需要不同的人来批准,这样就可以运用责任链模式来处理。
比如:项目经理的只能批准员工三天以内的假期,其他的都需要上级来批准;
部门总监则可以批准员工一周以内的假期,其他的需要上级来批准;
总经理则可以批准员工任意天数的假期,还可以批准员工加薪情况;(比如:500以内批准,500以上的考虑一下。)
管理者类
public abstract class Manager
{
public Manager superior;
public String name ;
public Manager getSuperior()
{
return superior;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setSuperior(Manager superior)
{
this.superior =superior;
}
public abstract void requestApplictions(Request request);
}
项目经理类
public class ProgrammerManager extends Manager
{
public ProgrammerManager()
{
super();
}
public void requestApplictions(Request request)
{
if ("请假".equals(request.getRequestType()) && request.getNum() <=3)
{
System.out.println(getName() +"向项目经理"+ request.getRequestType() +request.getNum() +"天,被批准!");
}
else
{
if (getSuperior()!=null)
{
this.getSuperior().requestApplictions(request);
}
}
}
}
部门总监类
public class MajorManager extends Manager
{
public MajorManager()
{
super();
}
public void requestApplictions(Request request)
{
if ("请假".equals(request.getRequestType()) && request.getNum() <=7)
{
System.out.println(getName() +"向总监"+ request.getRequestType() +request.getNum() +"天,被批准!");
}
else
{
if (getSuperior()!=null)
{
this.getSuperior().requestApplictions(request);
}
}
}
}
总经理类
public class GenaralManager extends Manager
{
public GenaralManager()
{
super();
}
public void requestApplictions(Request request)
{
if ("请假".equals( request.getRequestType()))
{
System.out.println(getName() +"向总经理" + request.getRequestType() +",被批准!");
}
else if ("加薪".equals(request.getRequestType()) && request.getNum() <=500)
{
System.out.println(getName() +"向总经理提出" + request.getRequestType() +request.getNum()+",被批准!");
}
else if ("加薪".equals(request.getRequestType())&& request.getNum() >=500)
{
System.out.println(getName() +"向总经理提出" + request.getRequestType() +request.getNum()+",需要考虑一下!");
}
}
}
测试类
public class Request
{
private String requestType;
private int num;
public String getRequestType()
{
return requestType;
}
public void setRequestType(String requestType)
{
this.requestType=requestType;
}
public int getNum()
{
return num;
}
public void setNum(int num)
{
this.num = num;
}
}
public class TestChainRespon
{
public static void main(String[] args)
{
Manager m1 = new ProgrammerManager();
Manager m2 = new MajorManager();
Manager m3 = new GenaralManager();
m1.setName("jerry");
m2.setName("tom");
m3.setName("jack");
m1.setSuperior(m2);
m2.setSuperior(m3);
Request req = new Request();
req.setRequestType("请假");
req.setNum(3);
Request req2 = new Request();
req2.setRequestType("请假");
req2.setNum(5);
Request req3 = new Request();
req3.setRequestType("加薪");
req3.setNum(500);
Request req4 = new Request();
req4.setRequestType("加薪");
req4.setNum(1000);
m1.requestApplictions(req);
m1.requestApplictions(req2);
m1.requestApplictions(req3);
m1.requestApplictions(req4);
}
}
测试结果:
jerry向项目经理请假3天,被批准!
tom向总监请假5天,被批准!
jack向总经理提出加薪500,被批准!
jack向总经理提出加薪1000,需要考虑一下!
优势:
责任链的对象只能与后面的对象发生耦合度较低的关联,如此一来,编制处理者与责任链程序则显得相对简单了;
分离了请求与处理,使客户无需了解自己的请求有那个对象来处理;
促使程序可以灵活的更改处理对象的前后次序,并且可以灵活的更改处理对象的职责。
应用场景:
多个对象均可以处理一个请求,并且在处理请求时可以自动定位;
客户无须指定固定的接收者,既可以对众多对象发送请求;
动态确定,可以处理单个请求的对象群。
不好之处:一个请求极有可能到链的末端都得不到处理,或者因为没有正确配置而得不到处理。
struts 与责任链模式
Struts2的拦截器结构所进行的设计,体现了责任链模式的实现。Struts2的拦截器结构类似于某种堆栈,当一个请求发起时,一个堆栈执行多个拦截器和Action;
其次,拦截器的结构中Action被放置在堆栈的底部,堆栈的“后进先出”原则将使多个拦截器先取出来执行,才能时Action去处来执行。如此一来,必先形成某种递归形式的调用。