六大常用设计模式:三、代理模式

3.1、介绍

代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象。

代理模式优点:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能

被代理的对象:远程对象、创建开销大的对象需要安全控制的对象。

代理模式主要有三种形式:

  • 静态代理模式(基于接口实现)
  • 动态代理模式(基于接口实现,又称为JDK代理、接口代理)
  • Cglib代理模式(可以在内存动态地创建对象,而不需要实现接口,它是属于动态代理范畴)。

这种类型的设计模式属于结构型模式。

下面介绍静态代理模式和动态代理模式。

3.2、静态代理模式

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

举例:有房东要通过中介将房屋出租。

首先要有接口 Rent.java ,里面有方法 rent() 出租房屋:

public interface Rent {
    
    
    // 出租房屋
    void rent();
}

然后是被代理对象房东 Host.java 实现接口 Rent.java

public class Host implements Rent {
    
    
    @Override
    public void rent() {
    
    
        System.out.println("有房东要出租房屋");
    }
}

同样的,代理对象中介 Intermediary.java 也要实现接口 Rent.java

public class Intermediary implements Rent {
    
    
    private Host host;
    public Intermediary(Host host) {
    
    
        this.host = host;
    }
    @Override
    public void rent() {
    
    
        System.out.println("中介开始代理房东………");
        // 交给中介把房子租出去
        host.rent();
        System.out.println("代理结束……………………");
    }
}

最后,客户端 Client.java 实现中介代理房东将房屋出租:

public class Client {
    
    
    public static void main(String[] args) {
    
    
        // 房东通过中介把房子租出去
        Host host = new Host();
        Intermediary intermediary = new Intermediary(host);
        intermediary.rent();
    }
}

运行结果如图:

在这里插入图片描述

总结:定义一个接口,让被代理对象和代理对象都实现该接口,代理对象中是用的静态代理方式实现接口,最后调用代理对象的方法调用目标对象。重点被代理对象和代理对象要实现相同的接口,然后通过调用相同的方法来调用被代理对象的方法

3.3、动态代理模式

在动态代理模式中,被代理对象(即目标对象)仍需要实现接口,但代理对象不需要实现接口。

代理对象的生成,是利用 JDK 的 API 动态地在内存中构建代理对象。因此动态代理也叫做JDK代理、接口代理。

同样举例:有房东要通过中介将房屋出租。

接口 Rent.java 和目标对象房东 Host.java 的代码同上述静态代理中的一样。

中介 Intermediary.java 没有实现接口 Rent.java ,使用的方法 newProxyInstance()

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

public class Intermediary {
    
    
    private Object host;
    public Intermediary(Object host) {
    
    
        this.host = host;
    }
    // 给目标对象生成一个代理对象
    public Object getProxyInstance(){
    
    
        return Proxy.newProxyInstance(host.getClass().getClassLoader(),
                host.getClass().getInterfaces(),
                new InvocationHandler() {
    
    
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
                        System.out.println("动态代理开始…………");
                        Object result = method.invoke(host, args);
                        System.out.println("结束动态代理…………");
                        return result;
                    }
                });
    }
}

客户端 Client.java 实现中介代理房东将房屋出租:

public class Client {
    
    
    public static void main(String[] args) {
    
    
        Rent host = new Host();
        Rent intermediary = (Rent)new Intermediary(host).getProxyInstance();
        // 通过代理对象,调用目标对象的方法
        intermediary.rent();
    }
}

总结:代理类所在包是 java.lang.reflect.Proxy ;JDK实现代理只需要使用 newProxyInstance() 方法,但是该方法需要接收三个参数,完整的写法是 static object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) ,三个参数的意思分别是:

  1. ClassLoader loader :指定当前目标对象使用的类加载器,获取加载器的方法。
  2. Class<?>[] interfaces :目标对象实现的接口类型,使用泛型方法确认类型。
  3. InvocationHandler h :事件处理,执行目标对象的方法时,会出发事件处理器方法,会把当前执行的目标对象方法作为参数传入。

猜你喜欢

转载自blog.csdn.net/weixin_60808029/article/details/122607429