责任链模式的两种实现

查询侠
• 阅读 5556

实现一: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);
        }
    }
}

大功告成!

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
责任链和策略设计模式-基于Java编程语言
责任链和策略设计模式这两种设计模式非常实用,下面简单介绍一下我对这两种设计模式的理解和它们在Spring框架源码中的应用。
Wesley13 Wesley13
3年前
java实现23种设计模式之责任链模式
顾名思义,责任链模式(ChainofResponsibilityPattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。pa
一分钟学会、三分钟上手、五分钟应用,快速上手责任链框架详解 | 京东云技术团队
责任链模式是开发过程中常用的一种设计模式,在SpringMVC、Netty等许多框架中均有实现。我们日常的开发中如果要使用责任链模式,通常需要自己来实现,但自己临时实现的责任链既不通用,也很容易产生框架与业务代码耦合不清的问题,增加CodeReview的成本。
捉虫大师 捉虫大师
3年前
我好像发现了一个Go的Bug?
从一次重构说起这事儿还得从一次重构优化说起。最近在重构一个路由功能,由于路由比较复杂,需求变化也多,于是想通过责任链模式来重构,刚好这段时间也在SentinelGo中看到相关源码。用责任链模式,最大的好处是可以针对每次请求灵活地插拔路由能力,如:这样实现会在每次请求到来时去new出整个责任链,可以预见对象会频繁的创建、销毁。对Java来说,对象池
Stella981 Stella981
3年前
Apache commons chain 初探
Apachecommonschain是什么Apachecommonchain是对责任链设计模式的改造封装,让使用者更加方便的使用。简单回顾一下责任链设计模式在阎宏博士的《JAVA与模式》一书中开头是这样描述责任链(ChainofResponsibility)模式的:责任链模式是一种对象的行为模式。在
Wesley13 Wesley13
3年前
Java 设计模式
前言23种经典的模式,根据用途我们又可以分为三大类,分别为创建型模式、结构型模式和行为型模式。创建型模式创建型模式的作用就是创建对象,说到创建一个对象,最熟悉的就是new一个对象,然后set相关属性。但是,在很多场景下,我们需要给客户端提供更加友好的创建对象的方式,尤其是那种我们定义了类,但是需要提供给其他开发者用的时
Wesley13 Wesley13
3年前
Java设计模式之责任链模式
引入责任链模式责任链模式顾名思义,责任链模式(ChainofResponsibilityPattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会
Wesley13 Wesley13
3年前
00_设计模式之语言选择
设计模式之语言选择设计模式简介背景设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。设计模式(Designpattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的
Wesley13 Wesley13
3年前
C++ 常用设计模式(学习笔记)
设计模式1、工厂模式在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。工厂模式作为一种创建模式,一般在创建复杂对象时,考虑使用;在创建简单对象时,建议直接new完成一个实例对象的创建。1.1、简单工厂模式主要特点是需要在工厂类中做判断,从而创造相应的产品,当