代理模式是一种结构型设计模式,它提供了一个代理对象作为原始对象的替代,以控制对原始对象的访问。 代理对象充当了客户端与原始对象之间的中介角色,常用于对目标对象进行延迟加载、权限控制等处理。代理模式的应用场景包括Web开发、网络通信和游戏开发等。
本文目录导读:
代理模式是一种设计模式,它为其他对象提供一种代理以控制对这个对象的访问,这种模式通常用于在不修改原始类的情况下,通过引入一个代理类来实现对原始类的访问控制,代理模式的主要目的是提供一个接口,使得客户端可以通过这个接口来访问原始对象,而不需要知道原始对象的具体实现,这样可以降低系统的耦合度,提高代码的可维护性和可扩展性。
代理模式分为静态代理和动态代理两种,静态代理是在编译时就确定了代理类和被代理类的关系,而动态代理是在运行时动态生成代理类,本文将详细介绍这两种代理模式的特点、应用场景以及如何实现。
静态代理
1、特点
(1)静态代理是在编译时就确定了代理类和被代理类的关系,因此在编译时就会产生代理类的.class文件,这意味着静态代理可以在不修改原始类的情况下,通过引入一个代理类来实现对原始类的访问控制。
(2)静态代理的实现主要依赖于Java的反射机制,通过反射,我们可以在运行时获取到被代理类的Class对象,从而创建代理类的实例,并通过调用被代理类的方法来实现对原始对象的访问控制。
2、应用场景
(1)权限控制:通过代理模式,我们可以实现对系统资源(如文件、数据库等)的访问控制,我们可以创建一个文件访问代理类,该类实现了FileInputStream接口,并在内部持有一个FileOutputStream对象,当客户端通过FileInputStream对象读取文件时,实际上是通过FileOutputStream对象进行写操作,这样,我们就可以在运行时动态地控制对文件的访问权限。
(2)性能监控:通过代理模式,我们可以在不修改原始类的前提下,实现对原始对象的性能监控,我们可以创建一个性能监控代理类,该类实现了PerformanceMonitor接口,并在内部持有一个PerformanceMonitor对象,当客户端通过PerformanceMonitor接口获取性能数据时,实际上是通过PerformanceMonitor对象进行获取,这样,我们就可以在运行时动态地监控系统的性能指标。
动态代理
1、特点
(1)动态代理是在运行时动态生成代理类的,这意味着我们可以在不修改原始类的情况下,通过引入一个代理类来实现对原始类的访问控制。
(2)动态代理的实现主要依赖于Java的动态语言支持(DLS),通过DLS,我们可以在运行时创建一个实现了指定接口的匿名类,并在该匿名类中重写接口方法,这样,我们就可以在运行时动态地生成代理类的实例,并通过调用被代理类的方法来实现对原始对象的访问控制。
2、应用场景
(1)AOP(面向切面编程):通过动态代理,我们可以将横切关注点(如日志记录、事务管理等)与业务逻辑分离,从而实现模块化和解耦,我们可以创建一个日志记录代理类,该类实现了LogInterceptor接口,当客户端通过被代理的方法调用时,实际上是通过日志记录代理类的方法进行调用,这样,我们就可以在运行时动态地插入日志记录代码,从而实现对业务逻辑的监控和管理。
(2)RPC(远程过程调用):通过动态代理,我们可以将远程方法调用(RMI)与本地方法调用相结合,从而实现跨平台和跨语言的通信,我们可以创建一个RPC客户端代理类,该类实现了RpcInvoker接口,当客户端通过RPC客户端代理类调用远程方法时,实际上是通过RPC服务器端代理类的方法进行调用,这样,我们就可以在运行时动态地将远程方法调用转换为本地方法调用,从而实现跨平台和跨语言的通信。
实现示例
以下是一个简单的静态代理和动态代理的实现示例:
1、静态代理实现示例:
// 被代理类 public class Subject { public void request() { System.out.println("Subject: Handling request."); } } // 代理类 public class RealSubjectProxy extends Subject implements ISubjectProxy { private ISubjectReal subjectReal; @Override public void request() { System.out.println("RealSubjectProxy: Pre-processing before forwarding the request to real subject."); subjectReal.request(); System.out.println("RealSubjectProxy: Post-processing after forwarding the response from real subject."); } } // 客户端代码 public class Client { public static void main(String[] args) { ISubjectProxy proxy = new RealSubjectProxy(); proxy.request(); // 输出:RealSubjectProxy: Pre-processing before forwarding the request to real subject. -> Subject: Handling request. -> RealSubjectProxy: Post-processing after forwarding the response from real subject. } }
2、动态代理实现示例:
// 被代理接口 public interface ISubjectReal { void request(); } // 实现被代理接口的类 public class RealSubject implements ISubjectReal { @Override public void request() { System.out.println("RealSubject: Handling request."); } } // 实现动态代理的工具类(InvocationHandler)和动态代理类(DynamicProxyDemo)如下: import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import java.util.logging.Logger; // 需要导入java.util.logging包才能使用Logger类型的对象logWriter和logRecord方法,如果没有导入该包,请自行定义Logger类型的对象或者使用其他日志库如log4j、logback等,这里为了简化示例,直接使用了System.out作为日志输出方式,实际开发中请根据需要选择合适的日志库或方式,本示例中的日志级别设置为INFO级别,可以根据实际情况调整为其他级别。