责任链模式其实是相对复杂的一个设计模式,所以一直不敢写这篇文章,在网上看了不少相关责任链模式的文章和视频才终于有所清醒,但是认识可能还是会很片面甚至出现错误,欢迎在评论区中指出。
1、责任链模式的优点
请求发送者、请求处理者之间的解耦
2、责任链模式的概念
引用百度百科:
责任链模式是一种设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。
3、责任链模式的角色
抽象处理者、具体处理者、责任链
4、责任链模式的应用场景
有多种请求、多种处理方式(处理方式或许会随着事件、时间等变化而变化)
分析:如果不将处理方式连接成一个整体,那么,每次进来一个请求,我们就必须判断它是属于哪一种处理方式,然后再用该种处理方式去解决这个请求,这时,请求和处理方式的耦合度就会非常高
,不适合灵活扩展,不符合开闭原则(对于一个软件实体如类,其模块和函数必须对修改关闭,对扩展开放)
。所以,我们需要将所有的处理方式捆绑在一起,形成一个责任链,那么,无论是哪个请求,只需要用这个责任链整体去处理该请求即可。
4、案例分析
1)网站注册
背景:当用户注册时,需要填用户、密码、验证码,那么当注册请求提交后,就会先确认你的用户名是否合法、密码是否合法、验证码是否正确,如果以上处理全通过,则数据进入数据库并且网页提示注册成功,否则网页提示注册失败并且显示注册失败的原因(例如用户名不合法、密码不合法、验证码不正确)
A.原始做法:用if else
if(!DoesUserNamePass())
system.out.print("用户名不合法,注册失败")
else if(!DosePasswordPass())
system.out.print("用户密码不合法,注册失败")
else if(!DoseVerificationCodePass())
system.out.print("验证码不正确,注册失败")
else
system.out.print("注册成功!")
很明显,这种结构的拓展性非常差,如果新增或者删除一个处理不得不修改已经写好了的类,不符合开闭原则中一个软件实体如类,函数或者模块对修改关闭
的原则。
那么,我们如何能做到对修改关闭呢?
B.优化做法
定义出抽象处理者
public abstract class Handler {
Handler handler;
public Handler add(Handler handler) {
this.handler = handler;
}
public abstract void doHandler(Client client);
}
然后创建三个具体处理者去实现原始处理中的三种方法DoesUserNamePass()、DosePasswordPass()、DoseVerificationCodePass(),它们通过next指针连接。
由于比较简单,所以我就没有去敲代码贴在这里了,第二个案例有代码示例。
2)过滤器
背景:我们在网上发表言论的时候其实都会经过一个过滤器,例如网页会处理【script】(因为<>打出来就消失了,所以用[]替换了<>)类似的黑客代码,还会处理一些敏感词汇等,这时都需要过滤器。
分析:模拟JavaEE中的FilterChain来实现一个过滤器,经过四个具体处理类,为了模拟功能每经过一个具体处理类在请求或者回应处加该处理类的类名,值得注意的是当response返回时经过的顺序则是与request经过的过滤器顺序相反的(如图)。(即request经过过滤器1234,后台服务器处理了请求后返回response给浏览器时,response经过过滤器的顺序是4321)
抽象处理者:
package pattern.roc.request.response;
public interface Filter {
//接口主要是为了方便扩展,符合开闭原则,chain用于调用下一个指针的具体处理者
void doFilter(Request request,Response response,FilterChain chain);
}
具体处理者:(最好用单例)
package pattern.roc.request.response;
public class FaceFilter implements Filter{
private FaceFilter(){}
private static class Inner{
private static final FaceFilter INSTANCE=new FaceFilter();
}
public static FaceFilter getINSTANCE() {
return Inner.INSTANCE;
}
@Override
public void doFilter(Request request, Response response,FilterChain chain) {
// TODO Auto-generated method stub
String r=request.getRequest();
r=r+"Face+";
request.setRequset(r);
//调用chain的do然后在chain中调用下一具体处理者的do
chain.doFilter(request,response,chain);
r=response.getResponse();
r=r+"Face+";
response.setResponse(r);
}
}
package pattern.roc.request.response;
public class SensitiveFilter implements Filter{
private SensitiveFilter() {}
private static class Inner{
static final SensitiveFilter INSTANCE=new SensitiveFilter();//必须是final类型!!别忘了
}
public static SensitiveFilter getInstance() {
return Inner.INSTANCE;
}
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
// TODO Auto-generated method stub
String r=request.getRequest();
r=r+"Sensitive+";
request.setRequset(r);
chain.doFilter(request, response, chain);
r=response.getResponse();
r=r+"Sensitive+";
response.setResponse(r);
}
}
package pattern.roc.request.response;
public class URL_Filter implements Filter{
private URL_Filter(){}
private static final URL_Filter INSTANCE=new URL_Filter();
public static URL_Filter getINSTANCE() {
return INSTANCE;
}
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
// TODO Auto-generated method stub
String r=request.getRequest();
r=r+"URL+";
request.setRequset(r);
chain.doFilter(request, response, chain);
r=response.getResponse();
r=r+"URL+";
response.setResponse(r);
}
}
package pattern.roc.request.response;
public class HTML_Filter implements Filter{
private HTML_Filter() {}
private static volatile HTML_Filter instance;
public static HTML_Filter getInstance() {
if(instance==null)
synchronized(HTML_Filter.class) {
if(instance==null)
instance=new HTML_Filter();
}
return instance;
}
@Override
public void doFilter(Request request, Response response, FilterChain chain) {
// TODO Auto-generated method stub
String r=request.getRequest();
r=r+"HTML+";
request.setRequset(r);
chain.doFilter(request, response, chain);
r=response.getResponse();
r=r+"HTML+";
response.setResponse(r);
}
}
责任链:
package pattern.roc.request.response;
import java.util.ArrayList;
import java.util.List;
//实现Filter接口是为了方便加责任链条
public class FilterChain implements Filter{
int index=0;
List<Filter> filters=new ArrayList<>();
/*返回FilterChain才可以实现连续add,例如:A.add(B).add(C).add(D)-----
注意,因为FilterChain也实现了Filter接口,所以不仅可以add(具体处理者),
还可以add(责任链)*/
public FilterChain add(Filter f) {
filters.add(f);
return this;
}
@Override
public void doFilter(Request request, Response response,FilterChain chain) {
// TODO Auto-generated method stub
//依赖index来判断是否经过所有的过滤器
if(index==filters.size()) return;
Filter filter=filters.get(index);
index++;
filter.doFilter(request,response,this);
}
}
请求:
package pattern.roc.request.response;
public class Request {
String request;
public String getRequest() {
return request;
}
public void setRequset(String request) {
this.request = request;
}
}
回应:
package pattern.roc.request.response;
public class Response {
String response;
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
}
测试:
package pattern.roc.request.response;
public class MainTest {
public static void main(String[] args) {
Request request=new Request();
Response response=new Response();
FilterChain chain=new FilterChain();
//设置初始值
request.setRequset("");
response.setResponse("");
//设置责任链,注意,因为add()返回值为链条,所以可以连续add()
chain.add(HTML_Filter.getInstance())
.add(FaceFilter.getINSTANCE())
.add(URL_Filter.getINSTANCE())
.add(SensitiveFilter.getInstance());
//处理
chain.doFilter(request, response, chain);
//测试
System.out.println(request.getRequest());
System.out.println(response.getResponse());
}
}
测试结果: