责任链模式

责任链模式,web容器的filter,struts2的intercepter都是用的这个设计模式,一般常用的if,else,switch,case也都是用的这个模式,设计好一个处理流程,挨个流程节点进行处理!具体写个例子程序!

责任链模式_第1张图片 

如上图所示,有一个类(也可做成接口):Handler,内含一个handler对象successor表明责任链的下一个处理节点,返回值为handler,可以实现链式编程,处理方法handlerRequest,继承或实现的类:characterHandler,symbolHandler,numberHanler,使用类:application实现责任链的设计,及使用。(此处封装的不够好~

Handler类:

public class Handler{

    private Handler successor;

   publicHandlersetSuccessor(Handler successor) {//这样就很方便的可以用链式编程了,但是不符合set,get默认生成的方法的模式。。不知道如果在spring中进行注册时会不会有问题。。

        this.successor = successor;//设计调用顺序时

    }

    public Handler getSuccessor() {//用责任链进行处理时,实现这个处理节点对下一个处理节点的调用

        return successor;

    }

   public voidhandleRequest(char c) {//处理方法

        if(successor != null)

            successor.handleRequest(c);

    } }

numberHandler类,继承handler,并重写handlerRequest方法进行数字的处理,若不是数据的话,进入下一个处理器,这里实现了链式调用!

public classNumberHandler extends Handler {

    public void handleRequest(char c) {

        if(Character.isDigit(c)) {

            System.out.println("Number hasbeen handled");

        } else {

            getSuccessor().handleRequest(c);

       }}}

CharacterHandler类,继承handler,并重写handlerRequest方法。

public classCharacterHandler extends Handler {

    public void handleRequest(char c) {

        if(Character.isLetter(c)) {

            System.out.println("Characterhas been handled");

        }else {

            getSuccessor().handleRequest(c);

       }}}

SymbolHandler直接做处理,没有调用过程!这是责任链的最后一道关口~~

public classSymbolHandler extends Handler {

    public void handleRequest(char c) {

        System.out.println("Symbol hasbeen handled");

   }}

Application真实的实用类,定义了责任链的整个调用顺序!

public classApplication {

    public static void main(String[]args)throws IOException {

        Handler numberHandler = newNumberHandler();

        Handler characterHandler = newCharacterHandler();

        Handler symbolHandler = newSymbolHandler();

        numberHandler.setSuccessor(characterHandler)

.setSuccessor(symbolHandler);//进行链式编程,很方便!而且定义链子很直观!

       char c = 'A';

        numberHandler.handleRequest(c);

    }}


这就是责任链,还是很简单的!

(以下摘自别人的博客:http://hwhuang.iteye.com/blog/648032,对比发现,首先说明问题比我要清晰很多,这说明理解比我透彻,并且表述能力比我强很多;其次,有总结且很到位,说明概括能力强,并且,理解深刻。。)


而在Struts2中,其拦截器结构的设计,是一个典型的责任链模式的应用。首先将整个执行划分成若干相同类型的元素,每个元素具备不同的逻辑责任,并将他们纳入到一个链式的数据结构中(我们可以把堆栈结构也看作是一个递归的链式结构),而每个元素又有责任负责链式结构中下一个元素的执行调用。 这样的设计,从代码重构的角度来看,实际上是将一个复杂的系统,分而治之,从而使得每个部分的逻辑能够高度重用并具备高度可扩展性。所以,Interceptor结构实在是Struts2/Xwork设计中的精华之笔。

Struts2拦截器执行机理如下:

1.整个结构就如同一个堆栈,除了Action以外,堆栈中的其他元素是Interceptor

2.Action位于堆栈的底部。由于堆栈"先进后出"的特性,如果我们试图把Action拿出来执行,我们必须首先把位于Action上端的Interceptor拿出来执行。这样,整个执行就形成了一个递归调用

3.每个位于堆栈中的Interceptor,除了需要完成它自身的逻辑,还需要完成一个特殊的执行职责。这个执行职责有3种选择:

1)中止整个执行,直接返回一个字符串作为resultCode

2)通过递归调用负责调用堆栈中下一个Interceptor的执行

3)如果在堆栈内已经不存在任何的Interceptor,调用Action


另一个大牛对责任链更深入的理解:

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

适用场景:

1、有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;

2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;

3、处理一个请求的对象集合应被动态指定。

具体实例:

在大学里面当班干部,时常要向上级申请各方面的东西。譬如申请全班外出秋游,普通同学将申请表交给班长,班长签字之后交给辅导员,辅导员批准之后上交到主任办公室…就是这样,一个请求(这里是一份申请表)有时候需要经过好几个级别的处理者(这里是辅导员、主任)的审查才能够最终被确定可行与否。

在这里表现出来的是一个职责链,即不同的处理者对同一个请求可能担负着不同的处理方式、权限,但是我们希望这个请求必须到达最终拍板的处理者(否则秋游就没戏了)。这种关系就很适合使用职责链模式了。

记得第一次看到职责链模式的时候,我很惊讶于它能够把我们平时在代码中的 if..else.. 的语句块变成这样灵活、适应变化。例如:如果现在辅导员请长假了,但我们的秋游还是要争取申请成功呀,那么我们在 Client 类中可以不要创建 handler02,即不要将该处理者组装到职责链中。这样子处理比 if..else..好多了。或者说,突然来了个爱管闲事的领导,那么我照样可以将其组装到职责链中。
 
关于上面使用场景中提到的3个点:
1、处理者在运行时动态确定其实是我们在 Client 中组装的链所引起的,因为具体的职责逻辑就在链中一一对应起来;
2、因为不确定请求的具体处理者是谁,所以我们把所有可能的处理者组装成一条链,在遍历的过程中就相当于向每个处理者都提交了这个请求,等待其审查。并且在审查过程中,即使不是最终处理者,也可以进行一些请求的“包装”操作(这种功能类似于装饰者模式),例如上面例子中的签名批准;
3、处理者集合的动态指定跟上面的第1、2点类似,即在 Client 类中创建了所有可能的处理者。
 
不足之处:

1、对于每一个请求都需要遍历职责链,性能是个问题;

2、抽象处理者 AbstractHandler 类中的 handleRequest() 方法中使用了递归,栈空间的大小也是个问题。

 个人看法:

职责链模式对于请求的处理是不知道最终处理者是谁,所以是运行动态寻找并指定;而命令模式中对于命令的处理时在创建命令是已经显式或隐式绑定了接收者。

到这吧,这篇文章有点长,而且都是别人的东西,自己都没整理,甚至有点没理解透就网上贴了,现下12:38有点困了。。。


你可能感兴趣的:(责任链模式)