在Java中,代理模式(Proxy Pattern)是一种结构型设计模式,它用于为其他对象提供一种代理以控制对这个对象的访问。代理模式主要分为静态代理和动态代理两种形式。
### 静态代理
静态代理是在编译时就确定具体类的一种代理方式。它通常通过创建一个代理类,这个代理类实现了与目标对象相同的接口,并在其方法内部调用目标对象的方法来实现对目标对象的代理。
**示例代码**(简单版):
// 接口
interface Image {
void display();
}
// 目标对象
class RealImage implements Image {
private String filename;
RealImage(String filename) {
this.filename = filename;
loadFromDisk(filename);
}
@Override
public void display() {
System.out.println("Displaying " + filename);
}
private void loadFromDisk(String filename) {
System.out.println("Loading " + filename);
}
}
// 代理类
class ProxyImage implements Image {
private RealImage realImage;
private String filename;
ProxyImage(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
// 使用
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test.jpg");
image.display();
}
}
### 动态代理
动态代理是在运行时动态地创建代理类的一种代理方式。它主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。动态代理通常用于当我们不知道目标对象的具体类时,或者需要频繁地创建代理类时。
**示例代码**(基于接口的动态代理):
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Image {
void display();
}
class RealImage implements Image {
private String filename;
RealImage(String filename) {
this.filename = filename;
}
@Override
public void display() {
System.out.println("Displaying " + filename);
}
}
class ImageInvocationHandler implements InvocationHandler {
private Object target;
ImageInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在方法调用之前可以做一些处理
System.out.println("Before method " + method.getName());
// 调用目标对象的方法
Object result = method.invoke(target, args);
// 在方法调用之后可以做一些处理
System.out.println("After method " + method.getName());
return result;
}
// 获取动态代理的实例
@SuppressWarnings("unchecked")
public static <T> T getProxyInstance(T target, Class<T> interfaceType) {
return (T) Proxy.newProxyInstance(
interfaceType.getClassLoader(),
new Class<?>[]{interfaceType},
new ImageInvocationHandler(target)
);
}
}
// 使用
public class DynamicProxyPatternDemo {
public static void main(String[] args) {
Image realImage = new RealImage("test.jpg");
Image proxyImage = ImageInvocationHandler.getProxyInstance(realImage, Image.class);
proxyImage.display();
}
}
这两个示例分别展示了静态代理和动态代理的基本用法。静态代理在编译时确定代理关系,而动态代理在运行时确定代理关系,提供了更高的灵活性和可扩展性。