温馨提示×

温馨提示×

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

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

什么是代理模式

发布时间:2021-10-12 09:50:25 来源:亿速云 阅读:190 作者:iii 栏目:编程语言
# 什么是代理模式

## 目录
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. 扩展与其他模式的对比维度

向AI问一下细节

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

AI