责任链模式的两种实现

实现一: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<Filter> list) {
        this.list = list;
    }

    List<Filter> 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<Filter> list = new ArrayList<Filter>();
        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);
        }
    }
}

大功告成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值