设计模式-代理模式(静态代理 动态代理)
代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以附加额外的功能,如访问控制、日志记录、延迟初始化等,而不需要修改目标对象的代码。
代理模式分为静态代理和动态代理两种实现方式。
1. 静态代理
静态代理是在编译期间就确定下来的代理类,它直接实现了目标接口,对目标方法进行了包装和增强。
假设我们有一个Image
接口和它的实现类RealImage
,我们通过静态代理ImageProxy
来实现图片加载的延迟加载。
// 目标接口
interface Image {
void display();
}
// 真实主题类
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk(filename);
}
private void loadFromDisk(String filename) {
System.out.println("Loading image from disk: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// 静态代理类
class ImageProxy implements Image {
private RealImage realImage;
private String filename;
public ImageProxy(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
客户端代码:
public class StaticProxyDemo {
public static void main(String[] args) {
Image image = new ImageProxy("image.jpg");
image.display();
}
}
2. 动态代理
动态代理则是在运行时通过反射机制动态生成的代理类,它不需要预先定义代理类,更加灵活。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 目标接口同上
// 动态代理处理器
class DynamicProxyHandler implements InvocationHandler {
private Object target;
public DynamicProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method call: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After method call: " + method.getName());
return result;
}
}
客户端代码:
public class DynamicProxyDemo {
public static void main(String[] args) {
RealImage realImage = new RealImage("image.jpg");
Image proxyInstance = (Image) Proxy.newProxyInstance(
RealImage.class.getClassLoader(),
new Class[]{Image.class},
new DynamicProxyHandler(realImage)
);
proxyInstance.display();
}
}
3. 优点:
- 代理模式提供了一种对目标对象的访问控制手段,可以在不修改目标对象的基础上,增加额外的功能,如权限校验、日志记录等。
- 动态代理提高了系统的灵活性和可扩展性,可以在运行时根据需要动态创建代理对象,无需修改代码。
- 静态代理实现简单直观,适用于那些代理逻辑相对固定的情况。
4. 缺点:
- 静态代理需要为每一个目标类创建代理类,当目标类数量众多时,会导致类的数量激增,增加了系统的复杂度。
- 动态代理依赖于反射,可能会有性能开销,尤其是在大量使用时需要注意。
- 代理模式增加了系统的复杂度,尤其是对于新手来说,理解代理模式的工作原理和使用场景可能会有一定难度。