代理模式是一种结构型设计模式,它允许通过提供代理对象来控制对另一个对象的访问。代理对象充当客户端和实际目标对象之间的中介,以便可以在访问实际目标对象之前或之后执行一些附加操作。
在Java中,代理模式被广泛应用于各种场景,特别是在网络编程、AOP(面向切面编程)和延迟加载等方面。Java中的代理模式有两种类型:静态代理和动态代理。
静态代理
静态代理是手动编写代理类的一种形式,该代理类和目标对象实现相同的接口,并在方法执行前后增加额外的逻辑。以下是一个简单的例子,来说明静态代理的应用:
// 目标接口
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 image from disk: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + 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();
}
}
// 使用代理对象
public class Main {
public static void main(String[] args) {
Image image = new ProxyImage("test.jpg");
image.display();
}
}
在上面的例子中,RealImage是目标对象,ProxyImage是代理对象,它们都实现了Image接口。当客户端调用代理对象的display方法时,如果代理对象还没有创建实际目标对象,则会创建并调用实际目标对象的display方法。
静态代理的优点是简单易懂,易于实现。然而,它的缺点是当目标接口发生变化时,代理类和目标类都需要进行修改,且代理类只能代理一个目标类,无法灵活地处理多个目标类的代理。
动态代理
动态代理是在运行时生成代理对象的一种方式,它不需要手动编写代理类,而是通过使用java.lang.reflect.Proxy类和InvocationHandler接口来实现。以下是一个简单的例子来说明动态代理的应用:
// 目标接口
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 image from disk: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// 动态代理处理器
public class ImageProxyHandler implements InvocationHandler {
private Image realImage;
public ImageProxyHandler(Image realImage) {
this.realImage = realImage;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("display")) {
System.out.println("Before displaying image");
Object result = method.invoke(realImage, args);
System.out.println("After displaying image");
return result;
} else {
return method.invoke(realImage, args);
}
}
}
// 使用动态代理
public class Main {
public static void main(String[] args) {
Image realImage = new RealImage("test.jpg");
Image proxy = (Image) Proxy.newProxyInstance(
realImage.getClass().getClassLoader(),
realImage.getClass().getInterfaces(),
new ImageProxyHandler(realImage)
);
proxy.display();
}
}
在上面的例子中,RealImage是目标对象,ImageProxyHandler是动态代理处理器。当客户端调用代理对象的display方法时,会先调用代理处理器的invoke方法,在invoke方法中可以添加额外的逻辑。
动态代理的优点是可以在运行时生成代理对象,而不需要手动编写代理类。它还具有更高的灵活性,可以代理多个目标对象,并且可以处理目标接口发生变化的情况。但是,动态代理的缺点是性能比静态代理稍差,并且需要对目标对象进行接口或者抽象类的实现。
总结来说,代理模式是一种非常有用的设计模式,它可以在访问对象之前或之后执行一些额外的操作。在Java中,静态代理和动态代理是两种常见的代理方式,它们分别适用于不同的需求场景。静态代理适用于简单的代理需求,而动态代理则更加灵活,并且适用于复杂的代理需求。无论选择哪种代理方式,都可以通过代理模式来实现解耦和增加额外功能的目的。
评论 (0)