署理模式:控制对象访问的利器!
各人好!本日我们来聊聊计划模式中的署理模式(Proxy Pattern)。假如你曾经须要控制对某个对象的访问,大概在访问对象时添加额外的逻辑(如权限查抄、日志 纪录等),那么署理模式就是你的救星!本文基于《Head First 计划模式》的署理模式章节,通过生动的故事和 Java 代码示例,带你轻松把握署理模式的英华。我们还会探究署理模式在 JDK 和 Spring 等框架中的应用,让你真正明确它的实际代价。
1. 署理模式是什么?
署理模式是一种布局型计划模式,它答应通过一个署理对象来控制对另一个对象的访问。署理模式的焦点头脑是在不改变原始类的情况下,通过引入署理类来加强或控制对原始类的访问。
实用场景
- 须要控制对某个对象的访问(如权限查抄、耽误加载等)。
- 须要在访问对象时添加额外的逻辑(如日志
纪录、性能监控 等)。
- 须要为长途对象提供当地署理(如长途方法调用 RMI)。
2. 署理模式的实现
故事配景
小明开辟了一个图片查察器体系,体系中有一个 Image 类用于加载和表现图片。由于图片加载是一个耗时的操纵,小明盼望在图片真正表现之前,先表现一个占位符(如加载中…),并在图片加载完成后再表现实际图片。
标题出现
假如直接在 Image 类中实现加载逻辑,会导致图片查察器的性能降落,由于每次加载图片时都须要等候图片加载完成。
办理方案:署理模式
小明决定使用署理模式,通过引入一个署理类 ImageProxy 来控制对 Image 对象的访问。署理类可以在图片加载完成前表现占位符,并在图片加载完成后表现实际图片。
3. 代码实现
1. 界说接口
起首,我们界说一个接口 Image,包罗图片表现的方法。- // 图片接口
- interface Image {
- void display();
- }
复制代码 2. 实现真实对象
接下来,我们实现真实的图片类 RealImage,用于加载和表现图片。- // 真实图片类
- class RealImage implements Image {
- private String filename;
- public RealImage(String filename) {
- this.filename = filename;
- loadFromDisk();
- }
- private void loadFromDisk() {
- System.out.println("Loading image: " + filename);
- }
- @Override
- public void display() {
- System.out.println("Displaying image: " + filename);
- }
- }
复制代码 3. 实当署理对象
然后,我们实当署理类 ImageProxy,用于控制对 RealImage 对象的访问。- // 图片代理类
- class ImageProxy implements Image {
- private String filename;
- private RealImage realImage;
- public ImageProxy(String filename) {
- this.filename = filename;
- }
- @Override
- public void display() {
- if (realImage == null) {
- realImage = new RealImage(filename); // 延迟加载
- }
- realImage.display();
- }
- }
复制代码 4. 客户端代码
末了,我们编写客户端代码来测试署理模式。- public class ImageViewer {
- public static void main(String[] args) {
- Image image = new ImageProxy("photo.jpg");
- // 图片未加载时,代理类可以显示占位符
- System.out.println("Image will be loaded on demand.");
- // 第一次显示图片,触发加载
- image.display(); // 输出: Loading image: photo.jpg, Displaying image: photo.jpg
- // 第二次显示图片,无需重新加载
- image.display(); // 输出: Displaying image: photo.jpg
- }
- }
复制代码 4. 署理模式的优缺点
优点
- 职责清楚:署理类负责控制对真实对象的访问,真实对象只需关注焦点逻辑。
- 耽误加载:可以通过署理类实现耽误加载,进步体系性能。
- 加强功能:可以在不修改真实对象的情况下,通过署理类添加额外的功能(如权限查抄、日志
纪录等)。
缺点
- 增长复杂度:引入署理类会增长体系的复杂度。
- 性能开销:署理类大概会引入额外的性能开销(如方法调用的间接性)。
5. 署理模式在 JDK 和 Spring 中的应用
1. JDK 中的应用
- 动态署理:JDK 提供了 java.lang.reflect.Proxy 类,用于创建动态署理对象。动态署理可以在运行时天生署理类,常用于实现 AOP(面向切面编程)。
- RMI(长途方法调用):JDK 的 RMI 框架使用署理模式来实现长途对象的当地署理。
动态署理示例
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- // 接口
- interface Greeting {
- void sayHello();
- }
- // 真实对象
- class GreetingImpl implements Greeting {
- @Override
- public void sayHello() {
- System.out.println("Hello, World!");
- }
- }
- // 动态代理处理器
- class LoggingHandler implements InvocationHandler {
- private Object target;
- public LoggingHandler(Object target) {
- this.target = target;
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- System.out.println("Before method: " + method.getName());
- Object result = method.invoke(target, args);
- System.out.println("After method: " + method.getName());
- return result;
- }
- }
- // 客户端代码
- public class DynamicProxyDemo {
- public static void main(String[] args) {
- Greeting realObject = new GreetingImpl();
- Greeting proxy = (Greeting) Proxy.newProxyInstance(
- realObject.getClass().getClassLoader(),
- realObject.getClass().getInterfaces(),
- new LoggingHandler(realObject)
- );
- proxy.sayHello(); // 输出: Before method: sayHello, Hello, World!, After method: sayHello
- }
- }
复制代码 2. Spring 中的应用
- AOP(面向切面编程):Spring 的 AOP 模块使用署理模式来实现切面功能(如日志纪录、事件管理等)。Spring 支持 JDK 动态署理和 CGLIB 署理。
- 事件管理:Spring 的事件管理器通过署理模式来控制事件的开启、提交和回滚。
Spring AOP 示例
- import org.springframework.aop.framework.ProxyFactory;
- import org.springframework.aop.support.DefaultPointcutAdvisor;
- import org.springframework.aop.support.NameMatchMethodPointcut;
- // 接口
- interface Service {
- void perform();
- }
- // 真实对象
- class ServiceImpl implements Service {
- @Override
- public void perform() {
- System.out.println("Performing service...");
- }
- }
- // 切面类
- class LoggingAspect {
- public void before() {
- System.out.println("Before method execution.");
- }
- public void after() {
- System.out.println("After method execution.");
- }
- }
- // 客户端代码
- public class SpringAOPDemo {
- public static void main(String[] args) {
- Service realObject = new ServiceImpl();
- ProxyFactory proxyFactory = new ProxyFactory(realObject);
- // 创建切点
- NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
- pointcut.addMethodName("perform");
- // 创建切面
- LoggingAspect aspect = new LoggingAspect();
- proxyFactory.addAdvisor(new DefaultPointcutAdvisor(pointcut, (method, args1, target) -> {
- aspect.before();
- Object result = method.invoke(target, args1);
- aspect.after();
- return result;
- }));
- // 获取代理对象
- Service proxy = (Service) proxyFactory.getProxy();
- proxy.perform(); // 输出: Before method execution., Performing service..., After method execution.
- }
- }
复制代码 6. 总结
署理模式通过引入署理类来控制对真实对象的访问,从而在不修改原始类的情况下加强或控制其举动。它的焦点上风在于:
- 职责分离:署理类负责控制访问,真实对象专注于焦点逻辑。
- 耽误加载:通过署理类实现耽误加载,提升体系性能。
- 加强功能:通过署理类添加额外功能(如日志纪录、权限查抄等)。
盼望本文能资助你更好地明确署理模式,并在实际项目中机动运用!
互动话题
你在项目中使用过署理模式吗?遇到过哪些风趣的标题?接待在批评区分享你的履历!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|