1. 什么是代理模式
定义
代理模式是一种结构型设计模式,通过为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和实际对象之间起到中介作用,可以在不改变真实对象的情况下增强或控制对真实对象的访问。
目的
代理模式的主要目的是隐藏对象的复杂性,控制对对象的访问,并在必要时增加一些额外的功能。这种模式对客户端透明,使客户端可以通过代理对象间接访问真实对象。
2. 代理模式的分类
静态代理
- 定义:静态代理是在编译期间就已经确定了代理关系,即代理类和被代理类的关系在程序运行之前就已经确定了。
- 实现:静态代理需要自己定义一个代理类,这个代理类需要实现和被代理类一样的接口,然后在代理类中调用被代理类的方法,并且可以在方法前后添加一些额外的逻辑。
代码示例:
public interface Subject {void request();
}public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("Real subject request.");}
}public class Proxy implements Subject {private RealSubject realSubject;@Overridepublic void request() {if (realSubject == null) {realSubject = new RealSubject();}preRequest();realSubject.request();postRequest();}private void preRequest() {System.out.println("Pre request processing.");}private void postRequest() {System.out.println("Post request processing.");}
}public class Client {public static void main(String[] args) {Subject proxy = new Proxy();proxy.request();}
}
动态代理
- 定义:动态代理是在运行期间动态生成代理类,也就是说代理类和被代理类的关系是在程序运行时动态生成的。
- 实现:动态代理需要使用Java提供的
Proxy
类和InvocationHandler
接口,通过实现InvocationHandler
接口的invoke()
方法来动态生成代理类。在调用代理类的方法时,会自动调用InvocationHandler
的invoke()
方法,在这个方法中可以对被代理类的方法进行拦截,并且可以在方法前后添加一些额外的逻辑。
代码示例:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public interface Subject {void request();
}public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("Real subject request.");}
}public class ProxyHandler implements InvocationHandler {private Object realSubject;public ProxyHandler(Object realSubject) {this.realSubject = realSubject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {preRequest();Object result = method.invoke(realSubject, args);postRequest();return result;}private void preRequest() {System.out.println("Pre request processing.");}private void postRequest() {System.out.println("Post request processing.");}
}public class Client {public static void main(String[] args) {RealSubject realSubject = new RealSubject();Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),new ProxyHandler(realSubject));proxy.request();}
}
3. 代理模式结构图
- 抽象主题(Subject):定义了真实主题和代理主题的共同接口,这样代理就可以在任何时候代替真实主题。
- 真实主题(Real Subject):定义了代理所代表的对象,是代理所要代理的对象。
- 代理(Proxy):提供了与真实主题相同的接口,同时还负责创建和删除真实主题对象,使得客户端不直接与真实主题进行交互。
- 客户端(Client):通过代理访问真实主题对象。
在代理模式中,代理与真实主题实现相同的接口,从而使得客户端可以透明地使用代理来访问真实主题对象。代理可以在真实主题操作之前或之后执行一些附加操作,从而对真实主题进行控制。
4. 代理模式的优缺点和应用场景
优点
- 中介作用:在客户端与目标对象之间起到一个中介作用和保护目标对象的作用。
- 功能扩展:代理对象可以扩展目标对象的功能。
- 降低耦合度:代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度。
缺点
- 增加复杂度:增加了系统的复杂度。
应用场景
- 功能增强:当需要对一个对象的访问提供一些额外操作时,可以使用代理模式。
- 远程(Remote)代理:通过远程代理,将网络通信、数据编解码等细节隐藏起来。客户端在使用RPC服务时,就像使用本地函数一样,无需了解跟服务器交互的细节。
- 防火墙(Firewall)代理:将浏览器配置成使用代理功能,防火墙将浏览器的请求转给互联网,当互联网返回响应时,代理服务器再把它转给浏览器。
- 保护(Protect or Access)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。