前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【设计模式之责任链模式】

【设计模式之责任链模式】

作者头像
用户5640963
发布2020-03-19 09:52:14
4120
发布2020-03-19 09:52:14
举报
文章被收录于专栏:卯金刀GG卯金刀GG

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

2、实现代码:

Chain接口

代码语言:javascript
复制
/**
 * @Author: Liu Yue
 * @Descripition:
 * @Date; Create in 2020/3/14 22:23
 **/
public interface Chain {
    void next();
}
/**
 * @Author: Liu Yue
 * @Descripition:
 * @Date; Create in 2020/3/16 8:53
 **/
public class Member {
}

ChainHandler

代码语言:javascript
复制
/**
 * @Author: Liu Yue
 * @Descripition:
 * @Date; Create in 2020/3/14 22:29
 **/
public abstract class ChainHandler<T> {

    protected ChainHandler next;

    public void next(ChainHandler next) {
        this.next = next;
    }

    public abstract void doHandler(Member member);

    public static class Builder<T> {
        private ChainHandler head = null;
        private ChainHandler tail = null;

        public Builder<T> addHandler(ChainHandler chain) {
            if (this.head == null) {
                this.head = this.tail = chain;
                return this;
            }
            this.tail.next(chain);
            this.tail = chain;
            return this;
        }

        public ChainHandler<T> build() {
            return this.head;
        }
    }
}

Chain实现类

代码语言:javascript
复制
/**
 * @Author: Liu Yue
 * @Descripition:
 * @Date; Create in 2020/3/14 22:26
 **/
public class FirstChain extends ChainHandler {

    @Override
    public void doHandler(Member member) {
        System.out.println("第一个关口");
        next.doHandler(member);
    }
}
public class SecondChain extends ChainHandler {

    @Override
    public void doHandler(Member member) {
        System.out.println("第二个关口");
        next.doHandler(member);
    }
}
public class ThirdChain extends ChainHandler {

    @Override
    public void doHandler(Member member) {
        System.out.println("第三个关口");
        if (member != null) {
            next.doHandler(member);
        }
    }
}

客户端测试类

代码语言:javascript
复制
/**
 * @Author: Liu Yue
 * @Descripition:
 * @Date; Create in 2020/3/16 8:49
 **/
public class ChainTest1 {

    public void chain(Member member) {
        ChainHandler.Builder builder = new ChainHandler.Builder();
        builder.addHandler(new FirstChain())
                .addHandler(new SecondChain())
                .addHandler(new ThirdChain());

        builder.build().doHandler(member);

    }

    public static void main(String[] args) {
        ChainTest1 chainTest1 = new ChainTest1();
        chainTest1.chain(new Member());
    }
}

3、servlet中的filter

代码语言:javascript
复制
public final class ApplicationFilterChain implements FilterChain {
    private int pos = 0; //当前执行filter的offset
    private int n; //当前filter的数量
    private ApplicationFilterConfig[] filters;  //filter配置类,通过getFilter()方法获取Filter
    private Servlet servlet
  
    @Override
    public void doFilter(ServletRequest request, ServletResponse response) {
        if (pos < n) {
            ApplicationFilterConfig filterConfig = filters[pos++];
            Filter filter = filterConfig.getFilter();
            filter.doFilter(request, response, this);
        } else {
            // filter都处理完毕后,执行servlet
            servlet.service(request, response);
        }
    }
}

4、dubbo中的filter

Dubbo在创建Filter的时候是另外一个方法,通过把Filter封装成 Invoker的匿名类,通过链表这样的数据结构来完成责任链。

Dubbo的责任链就没有类似FilterChain这样的类吧Filter和调用Invoker结合起来,而是通过创建一个链表,调用的时候我们只知道第一个节点,每个节点包含了下一个调用的节点信息。 这里的虽然Invoker封装Filter没有显示的指定next,但是通过java匿名类和final的机制达到同样的效果。

5、mybatis中的plugin

Mybatis可以配置各种Plugin,无论是官方提供的还是自己定义的,Plugin和Filter类似,就在执行Sql语句的时候做一些操作。Mybatis的责任链则是通过动态代理的方式,使用Plugin代理实际的Executor类。(这里实际还使用了组合模式,因为Plugin可以嵌套代理),核心代码如下:

代码语言:javascript
复制
public class Plugin implements InvocationHandler{
    private Object target;
    private Interceptor interceptor;
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {      
        if (满足代理条件) {
            return interceptor.intercept(new Invocation(target, method, args));
        }
        return method.invoke(target, args);     
    }
   
    //对传入的对象进行代理,可能是实际的Executor类,也可能是Plugin代理类
    public static Object wrap(Object target, Interceptor interceptor) {
  
        Class<?> type = target.getClass();
        Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
        if (interfaces.length > 0) {
            return Proxy.newProxyInstance(
                    type.getClassLoader(),
                    interfaces,
                    new Plugin(target, interceptor, signatureMap));
        }
        return target;
    }
} 

感谢博主: https://www.cnblogs.com/z-test/p/9319116.html

每天提高一点点

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档