设计模式:代理模式

代理模式(Proxy Pattern)是软件设计模式中的一种结构型模式,它提供了一种代理或占位符来控制对其他对象(称为真实主题或目标对象)的访问。代理模式的目的是为其他对象提供一层间接访问,以便可以控制对真实主题的访问、添加额外功能或改变其行为,而无需直接修改真实主题的代码。

代理模式的角色包括:

  1. Subject(抽象主题):这是真实主题和代理主题共同实现的接口或抽象类,声明了真实主题和代理主题都需支持的操作。

  2. RealSubject(真实主题):实现了Subject接口或抽象类,定义了代理所代表的真实对象。它是代理所代表的实际业务逻辑的真正实现。

  3. Proxy(代理):同样实现了Subject接口,包含对真实主题的引用,并且可以对真实主题的功能进行控制、扩展或限制。代理对象向客户端提供与真实主题相同的接口,但可能在调用真实主题的方法前后添加额外的操作。

代理模式的分类:

  • 静态代理:代理类在编译期间就已经确定,通常由程序员创建或特定工具生成源代码后编译而成。

  • 动态代理 :代理类在运行时动态生成,常见的动态代理实现方式有Java的java.lang.reflect.Proxy类和CGLIB库。这种代理更加灵活,可以根据需要在运行时创建不同的代理对象。

使用场景:

  • 延迟初始化:当创建对象开销较大时,可以使用代理模式延迟对象的创建,直到真正需要使用时才创建。

  • 权限控制:通过代理控制对真实对象的访问权限,例如在安全框架中对资源访问的控制。

  • 远程代理:为远程服务提供本地代理对象,隐藏网络通信的细节。

  • 日志、监控、统计:代理可以在调用前后添加日志记录、性能监控、计数等操作,而不影响原始对象的代码。

  • 懒加载:在需要时才加载对象,提高系统性能。

  • 增加额外功能:不修改原有对象的基础上,为其增加新的功能,比如缓存、事务处理等。

优点:

  • 松耦合:代理模式使得客户端和目标对象之间的耦合度降低。
  • 扩展性好:可以轻松添加代理类以支持新功能或修改现有功能,符合开闭原则。
  • 灵活性高:可以在不修改目标对象的前提下,控制对目标对象的访问。

缺点:

  • 增加系统复杂度:引入代理层会使系统结构变得更加复杂。
  • 性能开销:代理模式通常会带来一定的性能开销,尤其是动态代理,虽然开销不大,但在高性能要求的场合仍需考虑。

静态代理示例

首先,我们定义一个Subject接口,它是真实主题和代理主题共同遵循的接口:

java 复制代码
public interface Subject {
    void request();
}

接着,创建真实主题RealSubject类,实现Subject接口:

java 复制代码
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}

然后,创建静态代理类StaticProxy,它也实现了Subject接口,并在其内部持有RealSubject的实例,以控制对它的访问:

java 复制代码
public class StaticProxy implements Subject {
    private final RealSubject realSubject;

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

    @Override
    public void request() {
        preProcess();
        realSubject.request();
        postProcess();
    }

    private void preProcess() {
        System.out.println("StaticProxy: Preprocessing before calling real subject.");
    }

    private void postProcess() {
        System.out.println("StaticProxy: Postprocessing after calling real subject.");
    }
}

最后,客户端代码使用静态代理:

java 复制代码
public class Client {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Subject proxy = new StaticProxy(realSubject);
        proxy.request();
    }
}

动态代理示例

动态代理的实现通常利用Java的反射机制,这里我们使用JDK提供的java.lang.reflect.Proxy类来创建动态代理。首先,确保真实主题依然是上面定义的RealSubject类。

动态代理的实现涉及一个代理类的生成和InvocationHandler接口的使用:

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

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 {
        preProcess();
        Object result = method.invoke(target, args);
        postProcess();
        return result;
    }

    private void preProcess() {
        System.out.println("DynamicProxyHandler: Preprocessing before calling real subject.");
    }

    private void postProcess() {
        System.out.println("DynamicProxyHandler: Postprocessing after calling real subject.");
    }

    public static <T> T newProxyInstance(T realSubject) {
        return (T) Proxy.newProxyInstance(
                realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                new DynamicProxyHandler(realSubject)
        );
    }
}

客户端代码使用动态代理:

java 复制代码
public class DynamicProxyClient {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Subject proxy = DynamicProxyHandler.newProxyInstance(realSubject);
        proxy.request();
    }
}

以上就是使用Java实现静态代理和动态代理的基本示例。静态代理需要为每个真实主题手动创建代理类,而动态代理则可以在运行时动态生成代理对象,更加灵活。

相关推荐
吾与谁归in3 分钟前
【C#设计模式(4)——构建者模式(Builder Pattern)】
设计模式·c#·建造者模式
shinelord明5 分钟前
【再谈设计模式】建造者模式~对象构建的指挥家
开发语言·数据结构·设计模式
matrixlzp6 小时前
Java 责任链模式 减少 if else 实战案例
java·设计模式
编程、小哥哥8 小时前
设计模式之组合模式(营销差异化人群发券,决策树引擎搭建场景)
决策树·设计模式·组合模式
hxj..10 小时前
【设计模式】外观模式
java·设计模式·外观模式
吾与谁归in10 小时前
【C#设计模式(10)——装饰器模式(Decorator Pattern)】
设计模式·c#·装饰器模式
无敌岩雀11 小时前
C++设计模式行为模式———命令模式
c++·设计模式·命令模式
In_life 在生活21 小时前
设计模式(四)装饰器模式与命令模式
设计模式
瞎姬霸爱.21 小时前
设计模式-七个基本原则之一-接口隔离原则 + SpringBoot案例
设计模式·接口隔离原则
鬣主任1 天前
Spring设计模式
java·spring boot·设计模式