设计模式之结构型模式---代理模式

代理模式是一种结构型设计模式,它为目标对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用,客户端通过代理类与目标对象进行交互,而不是直接与目标对象进行交互。

代理模式的应用场景非常广泛,包括但不限于以下几种情况:

  1. 访问控制:当客户端不想或不能直接访问某个对象时,可以通过代理对象来间接访问。例如,当目标对象是一个远程服务或者是一个复杂且耗时的操作时,代理对象可以处理一些前置或后置的逻辑,如缓存、日志记录或权限验证等。
  2. 功能增强:代理模式可以在不修改目标对象代码的情况下,为目标对象添加额外的功能。代理对象可以在调用目标对象的方法前后添加新的逻辑,从而实现对目标对象的增强。
  3. 安全控制:在某些情况下,直接访问目标对象可能存在安全风险。通过代理对象,可以对访问进行过滤或限制,确保只有满足特定条件的客户端才能访问目标对象。

代理模式主要分为静态代理和动态代理两种类型:

  • 静态代理:在编译时就已经确定了代理类、接口和被代理类的关系。这种方式需要为每个被代理类手动编写代理类,因此当被代理类较多时,代码量会比较大。
  • 动态代理 :在运行时通过反射机制动态地创建代理类。这种方式不需要手动编写代理类,可以很方便地对代理类进行统一处理。Java中的java.lang.reflect.Proxy类和CGLIB库是实现动态代理的常用工具。

代理模式的优点包括:

  • 分离目标对象与客户端:客户端只与代理对象交互,降低了客户端与目标对象之间的耦合度。
  • 增加灵活性:通过代理对象,可以灵活地控制对目标对象的访问,实现访问控制、功能增强等目的。
  • 易于扩展:可以在不修改目标对象代码的情况下,为目标对象添加新的功能或行为。

好的,下面我将使用Java代码来描述代理模式中的静态代理和动态代理。

静态代理

假设我们有一个接口Subject和一个实现了该接口的类RealSubject,以及一个代理类ProxySubject

java 复制代码
// 接口定义
interface Subject {
    void request();
}

// 真实对象
class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("Called RealSubject.request()");
    }
}

// 代理对象
class ProxySubject implements Subject {
    private Subject realSubject;

    public ProxySubject(Subject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        // 在调用真实对象之前,可以添加一些预处理逻辑
        System.out.println("Before calling RealSubject.request()");
        realSubject.request();
        // 在调用真实对象之后,可以添加一些后处理逻辑
        System.out.println("After calling RealSubject.request()");
    }
}

// 客户端代码
public class StaticProxyDemo {
    public static void main(String[] args) {
        // 创建真实对象
        Subject realSubject = new RealSubject();
        // 创建代理对象,并将真实对象传递给代理对象
        Subject proxySubject = new ProxySubject(realSubject);
        // 客户端通过代理对象调用请求方法
        proxySubject.request();
    }
}

动态代理

在Java中,动态代理通常使用java.lang.reflect.Proxy类实现。下面是一个动态代理的示例:

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

// 接口定义(与静态代理中的相同)
interface Subject {
    void request();
}

// 真实对象(与静态代理中的相同)
class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("Called RealSubject.request()");
    }
}

// 调用处理器
class DynamicProxyHandler implements InvocationHandler {
    private Object subject;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用真实对象之前,可以添加一些预处理逻辑
        System.out.println("Before calling method: " + method.getName());
        Object result = method.invoke(subject, args);
        // 在调用真实对象之后,可以添加一些后处理逻辑
        System.out.println("After calling method: " + method.getName());
        return result;
    }
}

// 客户端代码
public class DynamicProxyDemo {
    public static void main(String[] args) {
        // 创建真实对象
        Subject realSubject = new RealSubject();
        // 创建调用处理器,并将真实对象传递给它
        InvocationHandler handler = new DynamicProxyHandler(realSubject);
        // 使用Proxy.newProxyInstance创建代理对象
        Subject proxySubject = (Subject) Proxy.newProxyInstance(
                RealSubject.class.getClassLoader(),
                new Class<?>[] { Subject.class },
                handler);
        // 客户端通过代理对象调用请求方法
        proxySubject.request();
    }
}

在动态代理中,Proxy.newProxyInstance方法用于生成代理对象,它接受三个参数:类加载器、代理类实现的接口数组以及调用处理器。调用处理器InvocationHandler负责处理代理实例上的方法调用,并决定是否以及如何调用实际对象上的方法。

需要注意的是,动态代理只能代理接口,如果要代理类,则需要使用如CGLIB这样的第三方库。

这些代码示例展示了如何在Java中实现静态代理和动态代理。静态代理需要手动编写代理类,而动态代理则通过反射机制在运行时动态生成代理类,提供了更大的灵活性和可扩展性。

相关推荐
晨米酱2 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机7 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机8 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机8 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机8 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤8 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴1 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤1 天前
工厂模式
设计模式