请问责任链真的是一种设计模式吗
坛子上讨论设计模式的也挺多的,但是关于这个责任链模式还没有人提及,我对责任链模式也有些疑惑,我的疑惑是,责任链真的是一种设计模式吗,我为什么有这种疑惑呢,因为在我用到和学习的责任链一共有3种,但是n多的书上就是那么一种最基础的责任链模式。在我的心里,只要能完成责任传递的都可以称之为责任链。当然也有可能我的这种理解是错误的,但如果我的理解是错误的,那么就是说每种模式都是有固定形态的,简单的模式是有固定形态,这我承认,但是如果说所有的模式都有固定的形态我不太相信,下面我就用文章来说明我的观点。
下面我详细说说我眼里的3种责任链模式:
1,基本版责任链
这里所谓的基本责任链模式是指书上网上到处都有的责任链模式,其实这种模式网上到处都有,我就炒炒冷菜。让我们来看看下面这个关于它的uml图
图1,见附件
这是最简单的责任链模式,但是事实上我很少看到它在真实的系统中被使用(也有可能经验不足)。大家看到,我在图中给接口和类取的名字是Filter,没错,这个模式待会将会和正真的Filter相比较。下面我们就看看在spring中如何实现这么一种责任链模式。
首先是Filter的接口如下:
/** * @author 张荣华(ahuaxuan) * {@link http://ahuaxuan.iteye.com} * @version $Id$ */public interface Filter {void executeFilter();}
/** * @author 张荣华(ahuaxuan) * {@link http://ahuaxuan.iteye.com} * @version $Id$ */public abstract class BaseFilter implements Filter {private Filter nextFilter;public void doNextFilter(){if (nextFilter != null) {nextFilter.executeFilter();} else {// do something you need here!System.out.println("there is no filter in the chain!!!!!!!!");}}/** * 该方法用来注入下一个filter * @param nextFilter */public void setNextFilter(Filter nextFilter) {this.nextFilter = nextFilter;}}
/** * @author 张荣华(ahuaxuan) * {@link http://ahuaxuan.iteye.com} * @version $Id$ */public class AuthFilter extends BaseFilter {public void executeFilter(){System.out.println("1------------check the user in this filter!");doNextFilter();System.out.println("2------------check the user in this filter!");}}
/** * @author 张荣华(ahuaxuan) * {@link http://ahuaxuan.iteye.com} * @version $Id$ */public class URLRewriteFilter extends BaseFilter {public void executeFilter(){System.out.println("1------------do url rewrite in this filter");doNextFilter();System.out.println("2------------do url rewrite in this filter");}}
/** * @author 张荣华(ahuaxuan) * {@link http://ahuaxuan.iteye.com} * @version $Id$ */public class OtherFilter extends BaseFilter {public void executeFilter(){System.out.println("1---------------do other things in this filter");doNextFilter();System.out.println("2---------------do other things in this filter");}}
<bean id="authFilter" value="urlRewriteFilter"></property> </bean> <bean id="urlRewriteFilter" value="otherFilter"></property> </bean><bean id="otherFilter" name="code">/** * @author 张荣华(ahuaxuan) * @version $Id$ */public class Subject extends Observable{/** * 业务方法,一旦执行某个操作,则通知观察者 */public void doBusiness(){if (true) {super.setChanged();}notifyObservers("mail");notifyObservers("jms");}public static void main(String [] args) {//创建一个被观察者Subject subject = new Subject();//创建两个观察者Observer mailObserver = new MailObserver();Observer jmsObserver = new JMSObserver();//把两个观察者加到被观察者列表中subject.addObserver(mailObserver);subject.addObserver(jmsObserver);//执行业务操作subject.doBusiness();}}
/** * @author 张荣华(ahuaxuan) * @version $Id$ */public class JMSObserver implements Observer{public void update(Observable o, Object arg) {if ("jms".equals(arg)) {System.out.println("发送消息给jms服务器的观察者已经被执行");}}}
/** * @author 张荣华(ahuaxuan) * @version $Id$ */public class MailObserver implements Observer{/** * 这个类取名为MailObserver,顾名思义,她是一个用来发送邮件的观察者 */public void update(Observable o, Object arg) {if ("mail".equals(arg)) {System.out.println("发送邮件的观察者已经被执行");}}}
private HandlerConfig [] handlerConfigs; private int firstElement = -1;private String doRegex;/** * 这个方法是核心方法,它根据正则表达式来决定哪些filter需要被执行,哪些filter不需要被执行 */public void executeHandler() {if (handlerConfigs == null) {// 调用业务方法return;}++firstElement;if (firstElement < handlerConfigs.length) {if (handlerConfigs[firstElement].getPattern().matcher(doRegex).matches()) {handlerConfigs[firstElement].getHandler().executeHandler(this);} else {this.executeHandler();}}}值得注意的是这个方法中有一个递规操作用,它的作用是当前handler不被执行的话就去判断是否执行下一个handler,我对递规还是有点怕的,大家有其他方法吗
/** * @author 张荣华(ahuaxuan) * {@link http://ahuaxuan.iteye.com } * @version $Id$ */public class AuthTestHandler implements Handler {public void executeHandler(HandlerChain handlerChain){System.out.println("1----------check the user in this filter!");handlerChain.executeHandler();System.out.println("2----------check the user in this filter!");}}
/** * @author 张荣华(ahuaxuan) * {@link http://ahuaxuan.iteye.com } * @version $Id$ */public class HandlerConfig {private Handler handler;private String handlerName;private String regex;private Pattern pattern;//省略getter和setter方法}
public static void main(String[] args) {HandlerConfig [] configs = new HandlerConfig[]{new HandlerConfig(), new HandlerConfig(), new HandlerConfig()};configs[0].setHandler(new AuthTestHandler());configs[0].setHandlerName("authFilter");configs[0].setRegex("\\d*");configs[1].setHandlerName("charsetFilter");configs[1].setHandler(new CharsetTestHandler());configs[1].setRegex("^[A-Za-z]+$");configs[2].setHandlerName("otherFilter");configs[2].setHandler(new OtherTestHandler());configs[2].setRegex("\\d*");System.out.println("chain1");EasyHandlerChain chain = new EasyHandlerChain("21");chain.setHandlerConfigs(configs);chain.executeHandler();System.out.println("");System.out.println("chain2");EasyHandlerChain chain1 = new EasyHandlerChain("asdf");chain1.setHandlerConfigs(configs);chain1.executeHandler();}
public void executeHandler(HandlerChain handlerChain){ System.out.println("1----------check the user in this filter!"); [b]handlerChain.executeHandler(); [/b] System.out.println("2----------check the user in this filter!"); }
++firstElement; if (firstElement < handlerConfigs.length) { if (handlerConfigs[firstElement].getPattern().matcher(doRegex).matches()) { handlerConfigs[firstElement].getHandler().executeHandler(this); } else { this.executeHandler(); } }
for (firstElement = 0; firstElement < handlerConfigs.length; firstElement++) { if (handlerConfigs[firstElement].getPattern().matcher(doRegex).matches()) { handlerConfigs[firstElement].getHandler().executeHandler(this);return;} }
public void executeHandler(HandlerChain handlerChain){ System.out.println("1----------check the user in this filter!"); [b]handlerChain.executeHandler(); [/b] System.out.println("2----------check the user in this filter!"); }
for (firstElement = 0; firstElement < handlerConfigs.length; firstElement++) { if (handlerConfigs[firstElement].getPattern().matcher(doRegex).matches()) { handlerConfigs[firstElement].getHandler().executeHandler(this);return;} }
for (firstElement = 0; firstElement < handlerConfigs.length; firstElement++) { if (handlerConfigs[firstElement].getPattern().matcher(doRegex).matches()) { handlerConfigs[firstElement].getHandler().executeHandler(this);return;} }
firstElement += 1; for (; firstElement < handlerConfigs.length ; firstElement++) { if (handlerConfigs[firstElement].getPattern().matcher(doRegex).matches()) { handlerConfigs[firstElement].getHandler().executeHandler(this); return; } }