最近了解druid时候,碰到这种设计模式,了解了一下,做个记录。
1、原理
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链。并沿着这条链传递该请求,直到有一个对象处理它为止。在这个链上的所有的对象有相同的接口(抽象类)但却有不同的实现。
常见应用:javax.servlet.Filter#doFilter()
参与者:
•抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对后继对象的引用。这个角色通常由一个抽象类或接口实现。
•具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给后继对象。由于具体处理者持有对后继对象的引用,因此,如果需要,具体处理者可以访问后继对象。
2、实例
/**
* 抽象处理者角色
* User: wayne
* Date: 12-11-8
* Time: 下午5:52
*/
public interface Filter {
public void doFilter(MyRequest request,MyResponse response,MyFilterChain filterChain);
}
定义三个具体处理角色:字符过滤器、登录过滤器、权限过滤器
/**
* 具体处理角色
* User: wayne
* Date: 12-11-8
* Time: 下午6:02
*/
public class AuthFilter implements Filter{
@Override
public void doFilter(MyRequest request, MyResponse response, MyFilterChain filterChain) {
request.setReqStr(request.getReqStr()+"[进行了权限过滤]");
filterChain.doFilter(request,response,filterChain);
response.setResp(response.getResp()+"[进行了权限过滤返回]");
}
}
/**
* 具体处理角色
* User: wayne
* Date: 12-11-8
* Time: 下午6:02
*/
public class EncodeFilter implements Filter{
@Override
public void doFilter(MyRequest request, MyResponse response, MyFilterChain filterChain) {
request.setReqStr(request.getReqStr()+"[进行了编码过滤]");
filterChain.doFilter(request,response,filterChain);
response.setResp(response.getResp()+"[进行了编码过滤返回]");
}
}
/**
* 具体处理角色
* User: wayne
* Date: 12-11-8
* Time: 下午6:02
*/
public class LoginFilter implements Filter{
@Override
public void doFilter(MyRequest request, MyResponse response, MyFilterChain filterChain) {
if(request.getReqStr().contains("root")){
request.setReqStr(request.getReqStr()+"[进行了登录过滤]");
filterChain.doFilter(request,response,filterChain);
response.setResp(response.getResp()+"[进行了登录过滤返回]");
} else{
request.setReqStr(request.getReqStr()+"[进行了登录过滤:登录不成功]");
response.setResp(response.getResp()+"[进行了登录过滤返回:登录失败]");
}
}
}
定义一根链子做串联用,这里注意这根链子也实现了Filter接口,这个的作用可以实现链子里面套链子
/**
* 责任链
* User: wayne
* Date: 12-11-8
* Time: 下午5:53
*/
public class MyFilterChain implements Filter{
private List<Filter> filters = new LinkedList<Filter>();
private MyRequest request;
private MyResponse response;
int index = 0;
public MyFilterChain() {
}
public MyFilterChain(MyRequest request, MyResponse response) {
this.request = request;
this.response = response;
}
public void addFilter(Filter filter){
this.filters.add(filter);
}
@Override
public void doFilter(MyRequest request, MyResponse response, MyFilterChain filterChain) {
if(index == filters.size())
return;
Filter filter = filters.get(index++);
filter.doFilter(request,response,this);
}
public MyRequest getRequest() {
return request;
}
public void setRequest(MyRequest request) {
this.request = request;
}
public MyResponse getResponse() {
return response;
}
public void setResponse(MyResponse response) {
this.response = response;
}
}
工具类
/**
* 模拟请求
* User: wayne
* Date: 12-11-8
* Time: 下午5:53
*/
public class MyRequest {
private String reqStr;
public String getReqStr() {
return reqStr;
}
public void setReqStr(String reqStr) {
this.reqStr = reqStr;
}
}
/**
* 模拟响应
* User: wayne
* Date: 12-11-8
* Time: 下午5:53
*/
public class MyResponse {
private String resp;
public String getResp() {
return resp;
}
public void setResp(String resp) {
this.resp = resp;
}
提供一个客户端
/**
* 责任链模式
* User: wayne
* Date: 12-11-8
* Time: 下午6:05
*/
public class Client {
/**
* 请求链:进入活动中心:[进行了编码过滤][进行了登录过滤][进行了权限过滤]
* 回应链:进入活动中心:[进行了权限过滤返回][进行了登录过滤返回][进行了编码过滤返回]
*
* 请求链:进入活动中心:[进行了编码过滤][进行了登录过滤:登录不成功]
* 回应链:进入活动中心:[进行了登录过滤返回:登录失败][进行了编码过滤返回]
*
* @param args
*/
public static void main(String[] args){
String reqMsg = "进入活动中心:";
MyRequest request = new MyRequest();
request.setReqStr(reqMsg);
String reqsMsg = "响应进入中心:";
MyResponse response = new MyResponse();
response.setResp(reqMsg);
MyFilterChain chain = new MyFilterChain();
chain.addFilter(new EncodeFilter());
chain.addFilter(new LoginFilter());
chain.addFilter(new AuthFilter());
chain.doFilter(request,response,chain);
System.out.println("请求链:"+request.getReqStr());
System.out.println("回应链:"+response.getResp());
}
}
至此,一个简单的责任链就实现了。
3、优点:
•责任链模式降低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这个请求。
•由于是在客户端来定义责任链的结构,可以动态地增加或修改处理一个请求的结构,增强了给对象指派职责的灵活性。
4、适用场合:
•有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
•想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
•可处理一个请求的对象集合应被动态指定。
•当一个方法的传入参数将成为分支语句的判断条件,分支条件存在扩展的可能,每一个分支的职责相对独立,且逻辑较为复杂时。
5、缺点
此处欢迎补充。
6、疑问
降低了请求的发送端和接收端之间的耦合这句,能否举个实际的例子?
此模式的缺点有哪些呢?
7、资料
设计模式学习总结-责任链模式(Chain of Responsibility Method)