Java中的代理模式与动态代理应用

D
dashen13 2024-10-11T13:04:15+08:00
0 0 183

代理模式是一种结构型设计模式,它允许通过提供代理对象来控制对另一个对象的访问。代理对象充当客户端和实际目标对象之间的中介,以便可以在访问实际目标对象之前或之后执行一些附加操作。

在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)