为了使多个对象都有机会处理一个请求(避免请求发送者和接受者之间的耦合关系),每个对象持有对下一个对象的引用,这些对象就形成一条链。请求来的时候沿着这条链传递该请求,直到有个对象处理它为止。例如,在Tomcat容器的设计中,一个TCP请求就是经过这样一条责任链传递下去,一直到最终处理这个请求的Servlet。【哪些对象可以处理请求?与Strut2中的拦截器有何区别?任一对象都可以处理请求,具体哪个对象来处理运行时决定。】所谓的解耦合,就是可以在不影响客户端的情况下,在这条链上增加处理节点。
例如,我们要在GUI应用程序中提供一些帮助信息,为了使这些帮助信息更具针对性和使用性,我们在不同的界面(如主界面、选项卡、对话跨)提供帮助按钮。那么,当用户点击帮助按钮之后,程序该如何处理这一请求才能返回最有用的帮助信息(很显然,处在不同界面需要的帮助也不太相同)?我们使用责任链模式来处理这一问题,这时候,发送请求的对象并不明确地直到谁是最终提供帮助的对象,这样就实现了解耦合(decouple)。
从第一个对象开始,要么亲自处理请求,要么转发给下一个对象,发送请求的对象无法确切直到那个对象处理请求提供帮助,因此我们说该请求有一个隐式的接受者(implicit receiver)。为了沿链转发请求,并保证接受者为隐式的,每个链上的对象都有一致的处理请求的接口和访问链上下一个对象的接口。例如,每个对象都提供一个名为handleHelp()的方法来处理请求,并持有下一对象的引用。
责任链(职责链)的类结构如下:
典型的对象结构如下:
责任链模式的参与者包括Client、Handler、ConcreteHandler
Client:向链上的具体处理者(ConcreteHandler)发送请求。
Handler:定义一个处理请求的接口
ConcreteHandler:处理它所负责的请求,可以访问它的下一对象,如果可以处理请求则处理,否则将该请求发送给下一对象。
Tomcat容器中的设计就采用该模式,从Engine到Host到Context到Wrapper。
管道(pipeline)和Valve
Tomcat通过pipeline和valve来拓展责任链的功能,pipeline就相当于链接各个对象的管道,里面传递的请求则像管道里的水,valve则相当于管道上方的小口子,让我们有机会接触里面的水,做一些额外的事情。
Java实例:
/**
*
*/
package designpattern.chain;
/**
* @author Brandon B. Lin
*
*/
public interface Handler {
public Handler getSuccessor();
public void setSuccessor(Handler successor);
public String handleRequest(String user, int fee);
}
/**
*
*/
package designpattern.chain;
/**
* @author Brandon B. Lin
*
*/
public abstract class SuperHandler implements Handler {
protected Handler successor;
@Override
public Handler getSuccessor() {
// TODO Auto-generated method stub
return successor;
}
@Override
public void setSuccessor(Handler successor) {
// TODO Auto-generated method stub
this.successor = successor;
}
@Override
public String handleRequest(String user, int fee) {
return null;
}
}
/**
*
*/
package designpattern.chain;
/**
* @author Brandon B. Lin
*
*/
public class ProjectManager extends SuperHandler {
@Override
public String handleRequest(String user, int fee) {
String result = "";
if(fee<=500) {
//为了测试,简单点,只同意张三的请求
if("张三".equals(user))
{
result = "成功:项目经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";
}else
{
//其他人一律不同意
result = "失败:项目经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
}
} else {
if(getSuccessor()!=null) {
return getSuccessor().handleRequest(user, fee);
}
}
return result;
}
}
/**
*
*/
package designpattern.chain;
/**
* @author Brandon B. Lin
*
*/
public class DeptManager extends SuperHandler {
@Override
public String handleRequest(String user, int fee) {
String result = "";
if(fee<=5000) {
//为了测试,简单点,只同意张三的请求
if("张三".equals(user))
{
result = "成功:部门经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";
}else
{
//其他人一律不同意
result = "失败:部门经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
}
} else {
if(getSuccessor()!=null) {
return getSuccessor().handleRequest(user, fee);
}
}
return result;
}
}
/**
*
*/
package designpattern.chain;
/**
* @author Brandon B. Lin
*
*/
public class GeneralManager extends SuperHandler {
@Override
public String handleRequest(String user, int fee) {
String result = "";
if(fee<=30000) {
//为了测试,简单点,只同意张三的请求
if("张三".equals(user))
{
result = "成功:总经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";
}else
{
//其他人一律不同意
result = "失败:总经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
}
} else {
if(getSuccessor()!=null) {
return getSuccessor().handleRequest(user, fee);
}
}
return result;
}
}
/**
*
*/
package designpattern.chain;
/**
* @author Brandon B. Lin
*
*/
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// 组装责任链
Handler h1 = new ProjectManager();
Handler h2 = new DeptManager();
Handler h3 = new GeneralManager();
h1.setSuccessor(h2);
h2.setSuccessor(h3);
//測試
String test1 = h3.handleRequest("张三", 300);
System.out.println("test1 = " + test1);
String test2 = h3.handleRequest("李四", 300);
System.out.println("test2 = " + test2);
System.out.println("---------------------------------------");
String test3 = h3.handleRequest("张三", 700);
System.out.println("test3 = " + test3);
String test4 = h3.handleRequest("李四", 700);
System.out.println("test4 = " + test4);
System.out.println("---------------------------------------");
String test5 = h3.handleRequest("张三", 1500);
System.out.println("test5 = " + test5);
String test6 = h3.handleRequest("李四", 1500);
System.out.println("test6 = " + test6);
}
}
参考资料:
Gamma:《设计模式》
http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html