代理模式(Proxy Pattern)
代理模式(Proxy Pattern)
是程序设计中的一种设计模式,其主要作用是为其他对象提供一种代理,以控制对这个对象的访问。以下是关于代理模式的详细解释:
代理模式定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
一、组成
- 抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
- 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
- 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
二、优点
- 职责清晰:真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完整事务,附带的结果就是编程简洁清晰。
- 中介和保护作用:代理对象可以在客户端和目标对象之间起到中介的作用,起到了中介的作用和保护了目标对象的作用。
- 高扩展性:模式结构包括真正的你要访问的对象(目标类)和代理对象,它们实现同一个接口,先访问代理类再访问真正要访问的对象。
三、缺点
- 请求处理速度可能变慢:由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
- 实现复杂度:实现代理模式需要额外的工作,有些代理模式的实现可能非常复杂。
四、实现方式
代理模式通常有两种实现方式:静态代理和动态代理。
- 静态代理:在编译时就已经确定代理类,代理类和目标类实现了相同的接口,客户端通过代理类来调用目标类的方法。静态代理需要手动编写代理类,并且对于每个目标类都需要编写一个对应的代理类,因此当目标类较多时,工作量会很大。
- 动态代理:动态代理是在运行时动态生成代理类,客户端通过动态代理类来调用目标类的方法。Java 中提供了两种动态代理的实现方式:基于接口的 JDK 动态代理和基于类的 CGLIB 动态代理。JDK 动态代理要求目标类必须实现一个或多个接口,而 CGLIB 动态代理则要求目标类不能被 final 修饰。
五、示例(以 JDK 动态代理为例)
以下是一个使用 JDK 动态代理实现代理模式的示例:
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("RealSubject: Handling request.");
}
}
// 代理主题角色
class ProxyHandler implements InvocationHandler {
private Object target;
public ProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args);
after();
return result;
}
private void before() {
System.out.println("ProxyHandler: Before method call.");
}
private void after() {
System.out.println("ProxyHandler: After method call.");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
InvocationHandler handler = new ProxyHandler(realSubject);
// 创建代理对象
Subject proxySubject = (Subject) Proxy.newProxyInstance(
RealSubject.class.getClassLoader(),
RealSubject.class.getInterfaces(),
handler
);
// 调用代理对象的方法
proxySubject.request();
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体