目录
责任链, 顾名思义是将多个节点通过链条的方式连接起来,每一个节点相当于一个对象,而每一个对象层层相关,直接或者间接引用下一个对象(节点);直到链条中有一个节点处理头节点传下来的事件截止。责任链模式是一种对象行为型模式。
为请求创建了一个接收者对象的链。
【晚上去上英语课,为了好开溜坐到了最后一排,哇,前面坐了好几个漂亮的MM哎,找张纸条,写上“Hi, 可以做我的女朋友吗?如果不愿意请向前传”,纸条就一个接一个的传上去了,糟糕,传到第一排的MM把纸条传给老师了,听说是个老处女呀,快跑!
责任链模式:在责任链模式中,很多对象由每一个对象对其下家的引用而接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。】
意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
何时使用:在处理消息的时候以过滤很多道。
如何解决:拦截的类都实现统一接口。
关键代码:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。
(1)优点
1、请求的发送者和接受者解耦。降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
2、增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
3、可以控制执行顺序。增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
4、责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
5、符合开闭原则和单一职责原则。责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
(2)缺点
1、不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
2、对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
3、职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
(3)使用场景
一个请求的处理需要多个对象当中的一个或几个协作处理。
有一事件,可以被多个对象同时处理,但是由哪个对象处理则在运行时动态决定。
在请求处理者不明确时向多个对象中提交一个请求。
动态指定一组对象处理请求。
(4)注意事项:
在 JAVA WEB 中遇到很多应用。如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
(5)应用实例:
1、红楼梦中的"击鼓传花"。
2、JS中的事件冒泡。
3、JAVA WEB中Apache Tomcat对Encoding的处理,Struts2的拦截器,jsp servlet的Filter。
(6)经典案例
1 javax.servlet.Filter
2 javax.servlet.FilterChain
代码
public class Main { public static void main(String[] args) { Msg msg = new Msg(); msg.setMsg("大家好:),<script>,欢迎访问 mashibing.com ,大家都是996 "); /* List<Filter> filters=new ArrayList<>(); filters.add(new HTMLFilter()); filters.add(new SensitiveFilter()); for (Filter f:filters){ f.doFilter(msg); } */ FilterChain fc = new FilterChain(); fc.add(new HTMLFilter()) .add(new SensitiveFilter()); FilterChain fc2 = new FilterChain(); fc2.add(new FaceFilter()).add(new URLFilter()); fc.add(fc2); fc.doFilter(msg); System.out.println(msg); } } class Msg { String name; String msg; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } @Override public String toString() { return "Msg{" + "msg='" + msg + '\'' + '}'; } } interface Filter { boolean doFilter(Msg m); } class HTMLFilter implements Filter { @Override public boolean doFilter(Msg m) { String r = m.getMsg(); r = r.replace('<', '['); r = r.replace('>', ']'); m.setMsg(r); return true; } } class SensitiveFilter implements Filter { @Override public boolean doFilter(Msg m) { String r = m.getMsg(); r = r.replaceAll("996", "955"); m.setMsg(r); return false; } } class FaceFilter implements Filter { @Override public boolean doFilter(Msg m) { String r = m.getMsg(); r = r.replace(":)", "^V^"); m.setMsg(r); return true; } } class URLFilter implements Filter { @Override public boolean doFilter(Msg m) { String r = m.getMsg(); r = r.replace("mashibing.com", "http://www.mashibing.com"); m.setMsg(r); return true; } } class FilterChain implements Filter { private List<Filter> filters = new ArrayList<>(); public FilterChain add(Filter f) { filters.add(f); return this; } public boolean doFilter(Msg m) { for(Filter f : filters) { if(!f.doFilter(m)) return false; } return true; } }