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

23种设计模式之代理模式

作者头像
暴躁的程序猿
发布2022-03-23 17:04:01
1460
发布2022-03-23 17:04:01
举报

代理模式(Proxy)

代理模式的基本介绍

1.代理模式:为一个对象提供一个替身,以控制对这个对象的访问,即通过代理对象访问目标对象…这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能

2.被代理对象可以使远程对象、创建开销大的对象或需要安全控制的对象

3.代理模式有不同的形式,主要有三种静态代理、动态代理(JDK代理、接口代理)、和cglib代理(可以在内存中动态的创建对象,而不需要实现接口,它是属于动态代理的范畴)

静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类

应用实例

1、定义一个接口ITeacherDao

2.目标对象TeacherDao实现ITeacherDao

3.使用静态代理方式,就需要在代理对象TeacherDaoProxy中也实现ITeacherDao

4.调用的时候通过调用代理对象的方法来调用目标对象

5.特别提醒:代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来 调用目标对象方法 接口

代码语言:javascript
复制
/**
 * 接口
 */
public interface ITeacherDao {
    /**
     * 授课的方法
     */
    void teach();
}

接口实现

代码语言:javascript
复制
/**
 * @create: 2021/10/6
 * @author: Tony Stark
 */
public class TeacherDao implements ITeacherDao {
    @Override
    public void teach() {
        System.out.println("老师授课中......");
    }

}

代理类实现接口

代码语言:javascript
复制
/**
 * 代理类  静态代理
 * @create: 2021/10/6
 * @author: Tony Stark
 */
public class TeacherDaoProxy implements ITeacherDao {

    /**
     *目标对象通过接口来聚合
     */
    private ITeacherDao target;

    /**
     * 构造器  构建TeacherDaoProxy对象是传进来一个接口 (实现了接口的具体子类对象)
     * @param target
     */
    public TeacherDaoProxy(ITeacherDao target) {
        this.target = target;
    }

    @Override
    public void teach() {
        //加入增强的方法
        System.out.println("代理开始  完成一些操作.......");
        //执行代理类的方法
        target.teach();
        //增强的步骤
        System.out.println("提交操作  代理结束.......");
    }
}

调用

代码语言:javascript
复制
/**
 * @create: 2021/10/6
 * @author: Tony Stark
 */
public class Client {
    public static void main(String[] args) {
        //被代理的对象
        TeacherDao teacherDao = new TeacherDao();
        //代理对象   把背代理对象传给代理对象
        TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
        //通过代理对象执行方法
        teacherDaoProxy.teach();
    }
}

输出

代码语言:javascript
复制
代理开始  完成一些操作.......
老师授课中......
提交操作  代理结束.......

静态代理优缺点:

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

2.缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类

3.一旦接口增加方法 就要修改所有

动态代理

1.动态代理,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理

2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象

3.动态代理也叫做:JDK代理、接口代理

JDK中生成代理对象API

1.代理类所在包:java.lang.reflect.Proxy

2.JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是

static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

我们把上面的静态代理改成动态代理

在这里插入图片描述
在这里插入图片描述

接口

代码语言:javascript
复制
/**
 * 接口
 */
public interface ITeacherDao {

    /**
     * 授课的方法
     */
    void teach();
}

实现类

代码语言:javascript
复制
/**
 * @create: 2021/10/6
 * @author: Tony Stark
 */
public class TeacherDao implements ITeacherDao {
    @Override
    public void teach() {
        System.out.println("老师正在授课...");
    }
}

代理

代码语言:javascript
复制
/**
 * @create: 2021/10/6
 * @author: Tony Stark
 */
public class ProxyFactory  {
    /**
     *维护一个目标对象
     */
    private Object target;

    /**
     * 构造器对target进行初始化
     * @param target
     */
    public ProxyFactory(Object target) {
        this.target = target;
    }

    /**
     * 给目标对象生成一个代理对象
     * @return
     */
    public Object getProxyInstance(){
        //参数说明:
        //ClassLoader loader   指定当前目标对象使用的类加载器  获取加载器的方法固定
        //Class<?>[] interfaces  目标对象(被代理对象)的接口类型  使用泛型的方式确认类型
        //target.getClass().getInterfaces()获取所有接口
        //InvocationHandler h  事件处理,执行目标对象方法时
        // 会触发事件处理器的方法,会把当前执行的目标对象方法作为参数传入
       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 invoke = method.invoke(target, args);
               return invoke;
           }
       });
    }
}

调用测试

代码语言:javascript
复制
   /**
     * @create: 2021/10/6
     * @author: Tony Stark
     */
    public class Client {
        public static void main(String[] args) {
            //创建目标对象
            ITeacherDao target = new TeacherDao();
            //给目标对象创建代理对象
            ProxyFactory proxyFactory = new ProxyFactory(target);
            //返回的是代理对象 一个Object  可以强转成ITeacherDao  不强转调不了方法
            ITeacherDao proxyInstance = (ITeacherDao) proxyFactory.getProxyInstance();
            //从这里可以看出内存中动态生成了代理对象 class com.sun.proxy.$Proxy0
            System.out.println(proxyInstance.getClass());
            proxyInstance.teach();
        }
    }

输出

代码语言:javascript
复制
class com.sun.proxy.$Proxy0
JDK代理开始
老师正在授课...
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-10-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 代理模式(Proxy)
  • 静态代理
  • 动态代理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档