首页 > 其他 > 详细

代理模式

时间:2021-02-07 09:55:19      阅读:20      评论:0      收藏:0      [点我收藏+]

代理模式的定义:

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式分类:

静态代理、动态代理(JDK代理和cglib代理)

静态代理和JDK代理都是实现接口,cglib是可以实现类。

静态代理:

目标对象类型的变量指向代理对象,然后调用方法的时候会执行代理对象的方法, 代理对象的方法里面重写或者调用了目标对象的方法,并且在方法执行前后添加了一些功能。

举例:老师生病了,找来代课老师。其中有一个共有的功能就是上课,代课老师只关注上课就好,擦黑板的行为交给别人就好(代理对象)

首先,构建接口,其中有一个共有的功能

//公用的功能
public interface ITeacher {
    void teach();
}

目标对象/真实对象

//目标对象
public class Teacher implements ITeacher {
    @Override
    public void teach() {
        System.out.println("开始上课!!!!");
    }
}

代理对象

//代理对象
public class TeacherProxy implements ITeacher {
    //代理对象中引入目标对象
    private ITeacher teacher;

    public TeacherProxy(ITeacher teacher) {
        this.teacher = teacher;
    }

    @Override
    public void teach() {
        System.out.println("擦黑板");
        teacher.teach();
        System.out.println("下课了!!!!");
    }
}

调用方法

public class Client {
    public static void main(String[] args) {
        //引入目标对象
        Teacher teacher = new Teacher();
        //引入代理对象
        TeacherProxy teacherProxy = new TeacherProxy(teacher);

        //通过代理对象 调用其中的方法
        teacherProxy.teach();
    }
}

结果

"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" "-javaagent:D:\study\IntelliJ IDEA 2019.2.1\lib\idea_rt.jar=55176:D:\study\IntelliJ IDEA 2019.2.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;D:\study\workspace\workspace_idea_designMode\out\production\Proxy" com.ccunix.staticProxy.Client
擦黑板
开始上课!!!!
下课了!!!!
静态代理的优缺点:

优点:在不修改目标对象功能的前提下,通过代理对象进行扩展功能。

缺点:因为目标对象和代理对象都实现了相同的接口,一旦接口中的方法增加,那么就需要维护代理对象和目标对象。

动态代理

动态代理介绍:

代理对象不需要实现接口,但是目标对象必须实现接口,否则不可以使用动态代理。这个是前提

代理对象的生成用到了JDK的API,也就是反射。动态的在内存中生成代理对象。

首先有个接口

public interface ITeacher {
    void teach();
    void sayHello();
}

目标对象

public class Teacher implements ITeacher {
    @Override
    public void teach() {
        System.out.println("开始上课!!!");
    }

    @Override
    public void sayHello() {
        System.out.println("同学们好!!");
    }
}

动态获得代理对象

public class ProxyFactory {
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }
    /*
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
    1、classloader类加载器  获取类加载器的方法是固定的
    2、interfaces 就是目标对象实现的接口
    3、InvocationHandler 使用匿名内部类获取
    * */
    public Object getInstanceProxy(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("JDK动态代理");
                        Object result = method.invoke(target, args);
                        System.out.println("下课吧!!!");
                        return result;
                    }
                });
    }
}

Client类

public class Client {
    public static void main(String[] args) {
        ITeacher teacher = new Teacher();
        //代理工厂会根据目标对象生成代理工厂
        ProxyFactory proxyFactory = new ProxyFactory(teacher);

        //获取代理对象
        ITeacher proxy = (ITeacher)proxyFactory.getInstanceProxy();
        proxy.sayHello();
     //说明会根据方法的名字和参数进行分辨要执行的是哪个方法 proxy.teach();

cglib动态代理

技术分享图片

最大的区别就是目标对象不需要再实现接口了,这个时候用目标对象的子类来实现代理,这就是cglib代理,Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类。

在AOP编程中如何选择代理模式:

1.目标对象需要实现接口,用JDK代理
2.目标对象不需要实现接口,用Cglib代理

目标对象

public class Teacher {
    public void teach(){
        System.out.println("开始上课");
    }
}

代理工厂

public class ProxyFactory implements MethodInterceptor {

    //聚合目标对象
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxyInstance(){
        //1、创建一个工具类
        Enhancer enhancer = new Enhancer();
        //2、设置父类
        enhancer.setSuperclass(target.getClass());
        //3、设置回调函数 就是去调用拦截器
        enhancer.setCallback(this);
        //4、创建子类对象,就是代理对象
        return enhancer.create();
    }

    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("擦黑板");
        Object result = method.invoke(target, args);
        System.out.println("下课吧!!!");
        return result;
    }
}

client类

public class Client {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        //通过工具类生成代理对象
        Teacher proxyInstance = (Teacher) new ProxyFactory(teacher).getProxyInstance();
        //代理对象执行方法时会触发拦截器,从而实现对目标对象方法的调用
        proxyInstance.teach();
    }
}

 

代理模式

原文:https://www.cnblogs.com/sc19/p/14383628.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!