1、模式介绍:
代理模式(Proxy Pattern)是一种结构型设计模式,它允许你在不改变客户端代码的情况下,向某个对象提供一个代理,以控制对该对象的访问。代理对象通常会在实际对象的方法调用前后添加一些附加逻辑,如权限控制、懒加载、日志记录等。
代理模式涉及以下几个角色:
接口(Subject):定义了代理类和真实类共同的接口。
真实类(RealSubject):实现了接口的具体类,它是真正执行操作的对象。
代理类(Proxy):也实现了接口,持有真实类的引用,并在调用真实类的方法前后进行一些额外的处理。
2、应用场景:
远程代理(Remote Proxy):为一个对象在不同地址空间提供局部代表。典型应用是 RMI(远程方法调用)。
虚拟代理(Virtual Proxy):根据需要创建开销大的对象。它在真正需要时才创建对象。
保护代理(Protection Proxy):控制对原始对象的访问。通常用于对象应该有不同的访问权限。
智能引用(Smart Reference):在访问对象时提供额外的功能,例如引用计数、缓存等。
3、优点:
控制对真实对象的访问,增加系统的灵活性。
可以对真实对象进行扩展,而不修改其代码。
提供了对目标对象额外的操作,如权限控制、延迟加载、日志记录等。
4、缺点:
增加了系统的复杂度,尤其是在使用保护代理时。
可能会影响请求的处理速度,因为增加了间接层。
5、代码实现:
/*** 代理接口** @author FM_南风* @date 2024/6/25 13:28*/
public interface Subject {void request();
}/*** 实体类** @author FM_南风* @date 2024/6/25 13:28*/
public class RealSubject implements Subject{@Overridepublic void request() {System.out.println("实体类的请求");}
}/*** 代理类** @author FM_南风* @date 2024/6/25 13:30*/
public class Proxy implements Subject {private RealSubject realSubject;@Overridepublic void request() {if (realSubject == null) {realSubject = new RealSubject();}preRequest();realSubject.request();postRequest();}private void preRequest() {System.out.println("代理类: 前置处理");}private void postRequest() {System.out.println("代理类: 后置处理");}
}/*** 应用** @author FM_南风* @date 2024/6/25 13:31*/
public class ProxyClient {public static void main(String[] args) {Subject proxy = new Proxy();proxy.request();}
}
6、结果展示:
7、拓展动态代理:
还可以使用动态代理来实现代理模式,它使用 java.lang.reflect.Proxy
类和 InvocationHandler
接口来动态地创建代理对象。动态代理可以在运行时动态地将代理逻辑添加到真实对象中,而不需要在编译时显式地创建代理类。
/*** 动态代理** @author FM_南风* @date 2024/6/25 13:37*/
public class ProxyInvocationHandler implements InvocationHandler {private Object realSubject;public ProxyInvocationHandler(Object realSubject) {this.realSubject = realSubject;}@Overridepublic Object invoke(Object o, Method method, Object[] objects) throws Throwable {System.out.println("动态代理类: 前置处理");Object result = method.invoke(realSubject, objects);System.out.println("动态代理类: 后置处理");return result;}
}/*** 动态代理应用** @author FM_南风* @date 2024/6/25 13:39*/
public class ProxyInvocationClient {public static void main(String[] args) {RealSubject realSubject = new RealSubject();Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),new ProxyInvocationHandler(realSubject));proxy.request();}
}