设计模式 责任链模式

目录

 

1.拦截器

2.责任链模式


1.拦截器

由于动态代理一般都比较难理解,程序设计者会设计一个拦截器接口供开发者使用,开发者只要知道拦截器接口的方法、含义和作用即可,无须知道动态代理是怎么实现的。
用JDK动态代理来实现一个拦截器的逻辑,为此先定义拦截器接口Interceptor

package com.learn.interceptor;

import java.lang.reflect.Method;

public interface Interceptor {

    /**真实对象前调用
     * @param proxy:proxy代理对象
     * @param target:真实对象
     * @param method:method方法
     * @param args:运行方法参数
     * @return
    * */
    public boolean before(Object proxy, Object target, Method method,Object[] args);
    /**
     * @param proxy:proxy代理对象
     * @param target:真实对象
     * @param method:method方法
     * @param args:运行方法参数
     * */
    public void around(Object proxy, Object target, Method method,Object[] args);
    /**
     * @param proxy:proxy代理对象
     * @param target:真实对象
     * @param method:method方法
     * @param args:运行方法参数
     * */
    public void after(Object proxy, Object target, Method method,Object[] args);
}

 这里定义了3个方法,before、around、after方法,分别给予这些方法如下逻辑定义。

  1. ·3个方法的参数为:proxy代理对象、target真实对象、method方法、args运行方法参数。
  2. ·before 方法返回boolean值,它在真实对象前调用。当返回为true时,则反射真实对象的方法;当返回为false时,则调用around方法。
  3. ·在before方法返回为false的情况下,调用around方法。
  4. ·在反射真实对象方法或者around方法执行之后,调用after方法。

实现这个Interceptor的实现类—Mylnterceptor

package com.learn.interceptor;

import java.lang.reflect.Method;

public class MyInterceptor implements Interceptor{
    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        System.err.println("反射方法前逻辑");
        //不反射被代理对象原有方法
        return false;
    }

    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("取代了被代理对象的方法");
    }

    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        System.err.println("反射方法后逻辑");
    }
}

它实现了所有的Interceptor 接口方法,使用JDK动态代理,就可以去实现这些方法在适当时的调用逻辑了。

在JDK动态代理中使用拦截器

package com.learn.interceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class InterceptorJdkProxy implements InvocationHandler {

    //真实对象
    private Object target;
    //拦截器全限定名
    private String interceptorClass=null;

    public InterceptorJdkProxy(Object target, String interceptorClass) {
        this.target = target;
        this.interceptorClass = interceptorClass;
    }

    /**
     * 绑定委托对象并返回一个代理占位
     * @param: target 真实对
     * @return 代理对象占位
     * */
    public static Object bind(Object target,String interceptorClass){
        //取得代理对象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),
                new InterceptorJdkProxy(target,interceptorClass));
    }

    /**
     * 通过代理对象调用方法,首先进入这个方法
     * @param proxy 代理对象
     * @param method 方法 被调用方法
     * @param args 方法的参数
     * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(interceptorClass==null){
            //没有设置拦截器则直接反射原有方法
            return method.invoke(target,args);
        }
        Object result=null;
        //通过反射生成拦截器
        Interceptor interceptor= (Interceptor) Class.forName(interceptorClass).newInstance();
        //调用前置方法
        if(interceptor.before(proxy,target,method,args)){
            //反射原有对象方法
            result=method.invoke(target,args);
        }else{
            //返回false执行around方法
            interceptor.around(proxy,target,method,args);
        }
        //调用后置方法
        interceptor.after(proxy,target,method,args);
        return result;
    }
}

这里有两个属性,一个是target,它是真实对象;另一个是字符串interceptorClass,它是一个拦截器的全限定名。解释一下这段代码的执行步骤。

  • 第1步,在bind方法中用JDK动态代理绑定了一个对象,然后返回代理对象。
  • 第2步,如果没有设置拦截器,则直接反射真实对象的方法,然后结束,否则进行第3步。
  • 第3步,通过反射生成拦截器,并准备使用它。
  • 第4步,调用拦截器的before方法,如果返回为true,反射原来的方法;否则运行拦截器的around方法。
  • 第5步,调用拦截器的after方法。
  • 第6步,返回结果。

拦截器可以进一步简化动态代理的使用方法,使程序变得更简单

测试MyInterceptor 拦截器

package com.learn.interceptor;

import com.learn.proxy.HelloWorld;
import com.learn.proxy.HelloWorldImpl;

public class Test {
    public static void main(String[] args) {
        HelloWorld proxy= (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),"com.learn.interceptor.MyInterceptor");
        proxy.sayHelloWorld();
    }
}

运行zhe'这段代码,得到以下结果

2.责任链模式

当一个对象在一条链上被多个拦截器拦截处理(拦截器也可以选择不拦截处理它)时,我们把这样的设计模式称为责任链模式,它用于一个对象在多个角色中传递的场景

定义三个拦截器

package com.learn.interceptor;

import java.lang.reflect.Method;

public class Interceptor1 implements Interceptor{
    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("[拦截器1]before方法");
        return true;
    }

    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {

    }

    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("[拦截器1]的after方法");
    }
}


------
package com.learn.interceptor;

import java.lang.reflect.Method;

public class Interceptor2 implements Interceptor{
    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("[拦截器2]before方法");
        return true;
    }

    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {

    }

    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("[拦截器2]的after方法");
    }
}

------
package com.learn.interceptor;

import java.lang.reflect.Method;

public class Interceptor3 implements Interceptor{
    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("[拦截器3]before方法");
        return true;
    }

    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {

    }

    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("[拦截器3]的after方法");
    }
}

测试责任链模式上的多拦截器

package com.learn.interceptor;

import com.learn.proxy.HelloWorld;
import com.learn.proxy.HelloWorldImpl;

public class TestInterceptor {
    public static void main(String[] args) {
        HelloWorld proxy1= (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),"com.learn.interceptor.Interceptor1");
        HelloWorld proxy2= (HelloWorld) InterceptorJdkProxy.bind(proxy1,"com.learn.interceptor.Interceptor2");
        HelloWorld proxy3= (HelloWorld) InterceptorJdkProxy.bind(proxy2,"com.learn.interceptor.Interceptor3");
        proxy3.sayHelloWorld();
    }
}

运行结果为

before方法按照从最后一个拦截器到第一个拦截器的加载顺序运行,而after方法则按照从第一个拦截器到最后一个拦截器的加载顺序运行。
从代码中可见,责任链模式的优点在王我们可以在传递链上加入新的拦截器,增加拦截逻辑,其缺点是会增加代理和反射,而代理和反射的性能不高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值