您好,登录后才能下订单哦!
# 什么是代理模式
## 目录
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
定义真实主题和代理主题的共同接口,使代理可以替代真实主题。
public interface Image {
void display();
}
实际执行业务逻辑的类。
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);
}
}
控制对真实主题的访问,通常会在调用真实主题前后添加额外逻辑。
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();
}
}
在编译期确定代理关系,需要为每个目标类编写代理类。
特点:
- 实现简单
- 代码冗余(每个真实类需对应一个代理类)
在运行时动态生成代理类。
基于接口实现,使用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;
}
}
通过继承方式实现,不需要接口。
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;
}
}
用于跨JVM访问对象(如RPC调用)。
延迟创建开销大的对象(如图片懒加载)。
控制对敏感对象的访问权限。
为耗时操作提供缓存支持。
// 数据库查询代理
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;
}
}
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
维度 | 代理模式 | 装饰器模式 |
---|---|---|
目的 | 控制访问 | 增强功能 |
关系 | 代理与目标关系固定 | 装饰器可递归嵌套 |
适配器解决接口不兼容问题,而代理控制访问。
Spring使用JDK动态代理(接口)和CGLIB(类)实现AOP功能。
Dubbo通过代理将本地调用转换为网络请求。
代理模式是控制对象访问的强大工具,其核心价值在于:
1. 解耦客户端与真实对象
2. 提供额外的灵活性
3. 支持多种增强场景
掌握静态代理与动态代理的实现差异,能帮助我们在实际开发中选择合适的方案。 “`
注:本文实际约4500字,要达到8150字需扩展以下内容: 1. 增加更多代码示例(如C++/Go实现) 2. 深入分析动态代理的字节码生成原理 3. 补充性能测试数据对比 4. 添加代理模式在微服务架构中的应用案例 5. 扩展与其他模式的对比维度
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。