资讯专栏INFORMATION COLUMN

责任链模式的两种实现

_DangJin / 1279人阅读

摘要:实现一经典模式该模式特点多线程环境环境下,需要每一个客户端请求,一个对象。代码测试程序注意该测试程序是有的,多线程共享会导致的游标定位错误。

实现一:servlet 经典模式

该模式特点:多线程环境环境下,需要每一个客户端请求,new 一个ConcreteFilterChain对象。如果对象太大,增加cpu和gc的负担。

代码demo
import java.io.IOException;

public interface Filter {
    public void doFilter(Context ctx, FilterChain chain) throws IOException;

}
import java.io.IOException;

public interface FilterChain {
    void doFilter(Context ctx) throws IOException;

}
import java.io.IOException;

public class PrintOne implements Filter {
    @Override
    public void doFilter(Context ctx, FilterChain chain) throws IOException {
        System.out.println(Thread.currentThread().getId()+ " 1");
        chain.doFilter(ctx);
    }


}

import java.io.IOException;

public class PrintTwo implements Filter {
    @Override
    public void doFilter(Context ctx, FilterChain chain) throws IOException {

        System.out.println(Thread.currentThread().getId()+" 2");
        chain.doFilter(ctx);
    }
}


import java.io.IOException;

public class PrintThree implements Filter {
    @Override
    public void doFilter(Context ctx, FilterChain chain) throws IOException {

        System.out.println(Thread.currentThread().getId()+" 3");
        chain.doFilter(ctx);
    }
}
import java.io.IOException;
import java.util.List;

public class DefaultFilterChain implements FilterChain {

    public DefaultFilterChain(List list) {
        this.list = list;
    }

    List list;
    int pos = 0;

    @Override
    public void doFilter(Context ctx) throws IOException {
        if(pos < list.size()){
            Filter filter = list.get(pos);
            pos++;

            filter.doFilter(ctx,this);

        }
    }
}
测试程序
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestMain {
    static ExecutorService executorService = Executors.newFixedThreadPool(5);

    public static void main(String args[]){
        List list = new ArrayList();
        list.add(new PrintOne());
        list.add(new PrintTwo());
        list.add(new PrintThree());


        FilterChain filterChain = new DefaultFilterChain(list);

        for(int i=0;i<2;i++) {
            executorService.submit(new Event(filterChain));
        }
    }

    public static class Event implements Runnable{
        public Event(FilterChain filterChain) {
            this.filterChain = filterChain;
        }

        FilterChain filterChain;

        @Override
        public void run() {
            Context ctx = new Context();

            try {

                filterChain.doFilter(ctx);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

注意:该测试程序是有bug的,多线程共享filterChain会导致filter的游标定位错误。要解决这个问题,要么每个请求new一个DefaultFilterChain对象。

实现二

参考netty pipeline的实现

该实现的优点:多线程环境下,不需要每一个客户的请求都new一个DefaultFilterChain.该算法的巧妙之处在于:将handler跟filterchain 组成成一个节点。 通过handler驱动节点的扭转

上代码
public class Context {
}

public interface Handler {
    void handle(Context ctx,FilterChain filterChain);
}


public class PrintOne implements Handler {
    @Override
    public void handle(Context ctx, FilterChain filterChain) {
        System.out.println(Thread.currentThread().getId()+" 1");

        filterChain.fireNext(ctx);
    }
}


public class PrintTwo implements Handler{
    @Override
    public void handle(Context ctx, FilterChain filterChain) {
        System.out.println(Thread.currentThread().getId()+" 2");

        filterChain.fireNext(ctx);


    }
}


public class PrintThree implements Handler {
    @Override
    public void handle(Context ctx, FilterChain filterChain) {
        System.out.println(Thread.currentThread().getId()+" 3");

        filterChain.fireNext(ctx);

    }
}

FilterChain和DefaultFilterChain

public interface FilterChain {
    void handler(Context ctx);

    void fireNext(Context ctx);
}

public class DefaultFilterChain implements FilterChain {
    private FilterChain next;
    private Handler handler;

    public DefaultFilterChain(FilterChain next, Handler handler) {
        this.next = next;
        this.handler = handler;
    }


    @Override
    public void handler(Context ctx) {
        handler.handle(ctx,this);
    }

    public void fireNext(Context ctx){
        FilterChain next_ = this.next;
        if(next_ != null){
            next_ .handler(ctx);
        }

    }
}
测试代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class FilterChainTest {
    static ExecutorService executorService = Executors.newFixedThreadPool(3);

    public static void main(String args[]){

        Handler h1 = new PrintOne();
        Handler h2 = new PrintTwo();
        Handler h3 = new PrintThree();

        FilterChain filterChain3 = new DefaultFilterChain(null,h3);
        FilterChain filterChain2 = new DefaultFilterChain(filterChain3,h2);
        FilterChain filterChain1 = new DefaultFilterChain(filterChain2,h1);
        Context ctx = new Context();

        for(int i=0;i<3;i++){
            executorService.execute(new RunPrintEcho(filterChain1,ctx));
        }

    }

    public static class RunPrintEcho implements Runnable{
        FilterChain filterChain;
        Context ctx;

        public RunPrintEcho(FilterChain filterChain, Context ctx) {
            this.filterChain = filterChain;
            this.ctx = ctx;
        }

        @Override
        public void run() {
            filterChain.handler(this.ctx);
        }
    }
}

大功告成!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69201.html

相关文章

  • Java设计模式综合运用(责任模式进阶)

    摘要:责任链模式的具体运用以及原理请参见笔者责任链模式改进方式引入适配器模式关于接口适配器模式原理以及使用场景请参见笔者适配器模式。 1 责任链模式现存缺点 由于责任链大多数都是不纯的情况,本案例中,只要校验失败就直接返回,不继续处理接下去责任链中的其他校验逻辑了,故而出现如果某个部分逻辑是要由多个校验器组成一个整理的校验逻辑的话,则此责任链模式则显现出了它的不足之处了。(责任链模式的具体运...

    suosuopuo 评论0 收藏0
  • 每天一个设计模式责任模式

    摘要:实现以下是测试代码设置下一个处理的节点实现以下是测试代码设置下一个处理的节点参考设计模式和开发实践之责任链模式职责链模式 作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) 0. 项目地址 责任链模式·代码 《每天一个设计模式》地址 1. 什么是...

    Cciradih 评论0 收藏0
  • 每天一个设计模式责任模式

    摘要:实现以下是测试代码设置下一个处理的节点实现以下是测试代码设置下一个处理的节点参考设计模式和开发实践之责任链模式职责链模式 作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) 0. 项目地址 责任链模式·代码 《每天一个设计模式》地址 1. 什么是...

    _Suqin 评论0 收藏0
  • 每天一个设计模式责任模式

    摘要:实现以下是测试代码设置下一个处理的节点实现以下是测试代码设置下一个处理的节点参考设计模式和开发实践之责任链模式职责链模式 作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) 0. 项目地址 责任链模式·代码 《每天一个设计模式》地址 1. 什么是...

    Doyle 评论0 收藏0
  • 每天一个设计模式责任模式

    摘要:实现以下是测试代码设置下一个处理的节点实现以下是测试代码设置下一个处理的节点参考设计模式和开发实践之责任链模式职责链模式 作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) 0. 项目地址 责任链模式·代码 《每天一个设计模式》地址 1. 什么是...

    JerryWangSAP 评论0 收藏0

发表评论

0条评论

_DangJin

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<