实现一: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);
}
}
}
【责任链模式的两种实现】大功告成!