设计模式-代理模式(Proxy)

一、代理模式概述

1.1 什么是代理模式

代理模式是一种设计模式,它为其他对象提供一个代理以控制对这个对象的访问。代理模式的主要目的是在不修改原始类的情况下,增加额外的功能。代理模式分为静态代理和动态代理两种。

静态代理:在编译时确定代理类,代理类与目标类实现相同的接口。

动态代理:在运行时动态生成代理类,代理类实现了InvocationHandler接口。

1.2 简单实现代理模式

// 定义一个接口
public interface IService {
    void doSomething();
}

// 实现接口的具体类
public class RealService implements IService {
    @Override
    public void doSomething() {
        System.out.println("RealService is doing something");
    }
}

// 代理类,实现IService接口
public class ServiceProxy implements IService {
    private IService realService;

    public ServiceProxy(IService realService) {
        this.realService = realService;
    }

    @Override
    public void doSomething() {
        System.out.println("ServiceProxy is doing something before");
        realService.doSomething();
        System.out.println("ServiceProxy is doing something after");
    }
}

// 测试类
public class Test {
    public static void main(String[] args) {
        IService realService = new RealService();
        IService proxyService = new ServiceProxy(realService);
        proxyService.doSomething();
    }
}

在这个示例中,RealService是目标类,ServiceProxy是代理类。当我们调用proxyService.doSomething()时,实际上是通过ServiceProxy来调用RealService的doSomething()方法。这样我们就可以在不修改RealService的情况下,为其添加额外的功能。

1.3 使用代理模式的注意事项

  • 1、代理模式会增加系统的复杂度,因此应该谨慎使用。只有在必要的情况下才应该使用代理模式。

  • 2、代理模式需要实现一个代理类,这个代理类需要与目标类实现相同的接口。如果目标类有很多方法,那么代理类的代码量会很大。

  • 3、代理模式可能会导致性能问题。因为每次访问目标对象时都需要通过代理类来访问,所以会增加一些额外的开销。

  • 4、代理模式可以用于保护目标对象的安全性。通过代理类来控制对目标对象的访问,可以防止未经授权的访问。

  • 5、代理模式可以用于延迟加载。在代理类中可以实现懒加载的逻辑,只有当真正需要访问目标对象时才会去创建目标对象。这样可以提高系统的性能。

  • 6、代理模式可以用于实现动态代理。通过Java的反射机制,可以在运行时动态地生成代理类,从而实现更加灵活的功能。

二、代理模式的用途

代理模式是一种常见的设计模式,它为其他对象提供一种代理以控制对这个对象的访问。这种模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用,代理对象可以扩展目标对象的功能,并且能将客户端与目标对象分离,从而在一定程度上降低了系统的耦合度,增加了程序的可扩展性。

以下是代理模式的一些主要用途:

  • 1、远程代理:为位于不同地址空间的对象提供代理服务,比如Java的RMI技术。

  • 2、虚拟代理:根据需要创建开销较大的对象,通过它来存储实例化需要很长时间的真实对象。例如,在Android中,BitmapFactory类使用虚拟代理来优化内存使用。

  • 3、安全代理:用于控制对原始对象的访问权限。在某些情况下,当真实对象不适合直接暴露给客户端时,可以使用代理模式来实现安全控制。

  • 4、智能指引:当调用真实的方法时,代理可以在方法执行前后进行一些处理。例如,在Spring AOP中,切面可以拦截方法的调用并进行处理。

  • 5、缓存代理:为一些开销很大的操作提供缓存功能。例如,在Hibernate中,一级缓存是默认开启的,二级缓存可以通过配置来实现。

  • 6、记录日志:在方法调用前后进行日志记录,以便进行调试或者监控。例如,在Spring AOP中,切面可以在方法执行前后进行日志记录。

三、代理模式实现方式

3.1 静态代理

静态代理模式是指在编译期就已经确定了代理类和被代理类的关系,代理类与被代理类都实现相同的接口。以下是一个简单的Java静态代理模式示例:

首先,定义一个接口Subject:

public interface Subject {
    void request();
}

然后,创建一个实现了Subject接口的实体类RealSubject:

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真实主题执行请求");
    }
}

接下来,创建一个代理类Proxy,它也实现了Subject接口,并在其内部持有一个RealSubject对象:

public class Proxy implements Subject {
    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("代理处理请求前的操作");
        realSubject.request();
        System.out.println("代理处理请求后的操作");
    }
}

最后,在主程序中创建RealSubject和Proxy对象,并调用它们的request方法:

public class Main {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Proxy proxy = new Proxy(realSubject);
        proxy.request();
    }
}

运行结果:

代理处理请求前的操作
真实主题执行请求
代理处理请求后的操作

3.2 动态代理

动态代理模式是一种设计模式,它允许在运行时创建对象。在 Java 中,可以使用 java.lang.reflect.Proxy 类来实现动态代理。以下是一个简单的示例:

首先,创建一个接口 Subject:

public interface Subject {
    void request();
}

然后,创建一个实现 Subject 接口的实体类 RealSubject:

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真实主题执行请求");
    }
}

接下来,创建一个调用处理器 InvocationHandler,用于处理代理对象的方法调用:

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

public class DynamicProxyHandler implements InvocationHandler {
    private Object target;

    public DynamicProxyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理处理请求前的操作");
        Object result = method.invoke(target, args);
        System.out.println("代理处理请求后的操作");
        return result;
    }
}

最后,使用 Proxy.newProxyInstance() 方法创建代理对象,并调用其方法:

import java.lang.reflect.Proxy;

public class DynamicProxyDemo {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        DynamicProxyHandler handler = new DynamicProxyHandler(realSubject);
        Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);
        proxy.request();
    }
}

运行上述代码,将输出以下内容:

代理处理请求前的操作
真实主题执行请求
代理处理请求后的操作
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一碗油泼面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值