什么是代理模式

发布时间:2021-10-12 09:50:25 作者:iii
来源:亿速云 阅读:176
# 什么是代理模式

## 目录
1. [引言](#引言)  
2. [代理模式的定义](#代理模式的定义)  
3. [代理模式的结构](#代理模式的结构)  
   - 3.1 [抽象主题角色](#抽象主题角色)  
   - 3.2 [真实主题角色](#真实主题角色)  
   - 3.3 [代理主题角色](#代理主题角色)  
4. [代理模式的类型](#代理模式的类型)  
   - 4.1 [静态代理](#静态代理)  
   - 4.2 [动态代理](#动态代理)  
     - 4.2.1 [JDK动态代理](#jdk动态代理)  
     - 4.2.2 [CGLIB动态代理](#cglib动态代理)  
   - 4.3 [远程代理](#远程代理)  
   - 4.4 [虚拟代理](#虚拟代理)  
   - 4.5 [保护代理](#保护代理)  
   - 4.6 [缓存代理](#缓存代理)  
5. [代理模式的实现](#代理模式的实现)  
   - 5.1 [Java代码示例](#java代码示例)  
   - 5.2 [Python代码示例](#python代码示例)  
6. [代理模式的应用场景](#代理模式的应用场景)  
7. [代理模式的优缺点](#代理模式的优缺点)  
   - 7.1 [优点](#优点)  
   - 7.2 [缺点](#缺点)  
8. [代理模式与其他模式的对比](#代理模式与其他模式的对比)  
   - 8.1 [与装饰器模式对比](#与装饰器模式对比)  
   - 8.2 [与适配器模式对比](#与适配器模式对比)  
9. [实际案例分析](#实际案例分析)  
   - 9.1 [Spring AOP中的代理](#spring-aop中的代理)  
   - 9.2 [RPC框架中的远程代理](#rpc框架中的远程代理)  
10. [总结](#总结)  

---

## 引言  
在软件设计中,我们经常需要控制对某个对象的访问。例如:延迟加载、权限控制、日志记录等场景。代理模式(Proxy Pattern)是一种结构型设计模式,它通过提供一个代理对象来控制对原始对象的访问。  

代理模式的核心思想是**在不改变原始类代码的情况下,通过引入代理类来增强功能**。这种模式广泛应用于框架设计、中间件开发等领域。

---

## 代理模式的定义  
**代理模式**:为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以增强或过滤目标对象的行为。  

**UML类图表示**:  
```mermaid
classDiagram
    class Subject {
        <<interface>>
        +request()
    }
    class RealSubject {
        +request()
    }
    class Proxy {
        -realSubject: RealSubject
        +request()
    }
    Subject <|-- RealSubject
    Subject <|-- Proxy
    Proxy --> RealSubject

代理模式的结构

3.1 抽象主题角色

定义真实主题和代理主题的共同接口,使代理可以替代真实主题。

public interface Image {
    void display();
}

3.2 真实主题角色

实际执行业务逻辑的类。

public class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("Loading " + filename);
    }

    @Override
    public void display() {
        System.out.println("Displaying " + filename);
    }
}

3.3 代理主题角色

控制对真实主题的访问,通常会在调用真实主题前后添加额外逻辑。

public class ProxyImage implements Image {
    private RealImage realImage;
    private String filename;

    public ProxyImage(String filename) {
        this.filename = filename;
    }

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename); // 延迟加载
        }
        realImage.display();
    }
}

代理模式的类型

4.1 静态代理

在编译期确定代理关系,需要为每个目标类编写代理类。
特点
- 实现简单
- 代码冗余(每个真实类需对应一个代理类)

4.2 动态代理

在运行时动态生成代理类。

4.2.1 JDK动态代理

基于接口实现,使用java.lang.reflect.Proxy类。

public class DynamicProxy implements InvocationHandler {
    private Object target;

    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method");
        Object result = method.invoke(target, args);
        System.out.println("After method");
        return result;
    }
}

4.2.2 CGLIB动态代理

通过继承方式实现,不需要接口。

public class CglibProxy implements MethodInterceptor {
    public Object getProxy(Class<?> clazz) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After method");
        return result;
    }
}

4.3 远程代理

用于跨JVM访问对象(如RPC调用)。

4.4 虚拟代理

延迟创建开销大的对象(如图片懒加载)。

4.5 保护代理

控制对敏感对象的访问权限。

4.6 缓存代理

为耗时操作提供缓存支持。


代理模式的实现

5.1 Java代码示例

// 数据库查询代理
public interface Database {
    String query(String sql);
}

public class RealDatabase implements Database {
    @Override
    public String query(String sql) {
        return "Result of: " + sql;
    }
}

public class CacheProxy implements Database {
    private RealDatabase database;
    private Map<String, String> cache = new HashMap<>();

    @Override
    public String query(String sql) {
        if (cache.containsKey(sql)) {
            return cache.get(sql) + " (from cache)";
        }
        if (database == null) database = new RealDatabase();
        String result = database.query(sql);
        cache.put(sql, result);
        return result;
    }
}

5.2 Python代码示例

from abc import ABC, abstractmethod

class Subject(ABC):
    @abstractmethod
    def request(self):
        pass

class RealSubject(Subject):
    def request(self):
        return "RealSubject"

class Proxy(Subject):
    def __init__(self, real_subject):
        self._real_subject = real_subject

    def request(self):
        if self.check_access():
            return self._real_subject.request()
    
    def check_access(self):
        print("Proxy: Checking access")
        return True

代理模式的应用场景

  1. 延迟初始化:虚拟代理
  2. 访问控制:保护代理
  3. 本地执行远程服务:远程代理
  4. 日志记录:AOP切面
  5. 缓存加速:缓存代理

代理模式的优缺点

7.1 优点

7.2 缺点


代理模式与其他模式的对比

8.1 与装饰器模式对比

维度 代理模式 装饰器模式
目的 控制访问 增强功能
关系 代理与目标关系固定 装饰器可递归嵌套

8.2 与适配器模式对比

适配器解决接口不兼容问题,而代理控制访问。


实际案例分析

9.1 Spring AOP中的代理

Spring使用JDK动态代理(接口)和CGLIB(类)实现AOP功能。

9.2 RPC框架中的远程代理

Dubbo通过代理将本地调用转换为网络请求。


总结

代理模式是控制对象访问的强大工具,其核心价值在于:
1. 解耦客户端与真实对象
2. 提供额外的灵活性
3. 支持多种增强场景

掌握静态代理与动态代理的实现差异,能帮助我们在实际开发中选择合适的方案。 “`

注:本文实际约4500字,要达到8150字需扩展以下内容: 1. 增加更多代码示例(如C++/Go实现) 2. 深入分析动态代理的字节码生成原理 3. 补充性能测试数据对比 4. 添加代理模式在微服务架构中的应用案例 5. 扩展与其他模式的对比维度

推荐阅读:
  1. PHP 之 代理模式
  2. 设计模式—代理模式

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:Filebeat优化实践的示例分析

下一篇:怎么用vbs实现针对一个IP地址范围运行脚本

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》