Java设计模式-代理模式

2023-05-06  本文已影响0人  小薯条学技术
image.png

简介

代理模式是一种结构型设计模式,它可以让我们通过一个代理对象来访问一个真实的目标对象,从而实现对目标对象的功能扩展或保护。代理模式的主要角色有三个:

代理模式可以帮助我们解决以下几种问题:

实现

根据代理模式的定义,我们可以用以下的类图来表示它的结构:

[图片上传失败...(image-3b6969-1683447929320)]

其中,Client是客户端类,它需要使用Subject接口提供的方法。Proxy是代理类,它持有一个RealSubject的引用,并且实现了Subject接口。RealSubject是真实类,它也实现了Subject接口,并且定义了具体的业务逻辑。

代理模式有多种类型,例如静态代理、动态代理等,代理模式也有自己的优缺点,使用时需要根据具体的场景和需求来选择合适的类型和方式。

静态代理实现

下面我们用Java代码来实现一个静态代理的例子:

// 抽象主题接口
public interface Subject {
    // 定义一个抽象方法
    void request();
}

// 真实主题类
public class RealSubject implements Subject {
    // 实现抽象方法
    @Override
    public void request() {
        // 真实的业务逻辑
        System.out.println("RealSubject is doing something...");
    }
}

// 代理主题类
public class Proxy implements Subject {
    // 持有一个真实主题的引用
    private RealSubject realSubject;

    // 构造方法,传入一个真实主题对象
    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    // 实现抽象方法
    @Override
    public void request() {
        // 在调用真实主题之前,可以执行一些额外操作
        System.out.println("Proxy is doing something before...");
        // 调用真实主题的方法
        realSubject.request();
        // 在调用真实主题之后,可以执行一些额外操作
        System.out.println("Proxy is doing something after...");
    }
}

// 客户端类
public class Client {
    public static void main(String[] args) {
        // 创建一个真实主题对象
        RealSubject realSubject = new RealSubject();
        // 创建一个代理对象,并传入真实主题对象
        Proxy proxy = new Proxy(realSubject);
        // 使用代理对象来调用抽象方法
        proxy.request();
    }
}
运行结果如下:
Proxy is doing something before...
RealSubject is doing something...
Proxy is doing something after...

从运行结果可以看出,代理对象在调用真实对象的方法之前和之后,都执行了一些额外的操作,从而对真实对象进行了增强或控制。

动态代理实现

动态代理是一种特殊的代理模式,它可以在运行时动态地创建代理对象,而不需要事先定义代理类。动态代理可以更灵活地适应不同的场景和需求,但是也更复杂和难以理解。

这个例子是使用JDK动态代理来实现一个日志代理,它可以在调用目标对象的方法之前和之后,记录相关的日志信息。代码如下:

// 抽象主题接口
public interface Subject {
    // 定义一个抽象方法
    void request();
}

// 真实主题类
public class RealSubject implements Subject {
    // 实现抽象方法
    @Override
    public void request() {
        // 真实的业务逻辑
        System.out.println("RealSubject is doing something...");
    }
}

// 日志处理器类,实现了InvocationHandler接口,用于定义代理逻辑
public class LogHandler implements InvocationHandler {
    // 持有一个目标对象的引用
    private Object target;

    // 构造方法,传入一个目标对象
    public LogHandler(Object target) {
        this.target = target;
    }

    // 实现invoke方法,用于调用目标对象的方法,并在之前和之后执行日志操作
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用目标对象之前,记录开始时间
        long startTime = System.currentTimeMillis();
        System.out.println("开始执行" + method.getName() + "方法...");
        // 调用目标对象的方法,并获取返回值
        Object result = method.invoke(target, args);
        // 在调用目标对象之后,记录结束时间和耗时
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        System.out.println("结束执行" + method.getName() + "方法,耗时" + duration + "毫秒");
        // 返回结果
        return result;
    }
}

// 客户端类
public class Client {
    public static void main(String[] args) {
        // 创建一个真实主题对象
        RealSubject realSubject = new RealSubject();
        // 创建一个日志处理器对象,并传入真实主题对象
        LogHandler logHandler = new LogHandler(realSubject);
        // 使用Proxy类的静态方法newProxyInstance来动态地创建一个代理对象,传入真实主题对象的类加载器、接口和处理器
        Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), logHandler);
        // 使用代理对象来调用抽象方法
        proxy.request();
    }
}

运行结果如下:

开始执行request方法...
RealSubject is doing something...
结束执行request方法,耗时1毫秒

从运行结果可以看出,代理对象在调用真实对象的方法之前和之后,都执行了一些日志操作,从而对真实对象进行了增强。

优缺点

静态代理模式

优点:

缺点:

动态代理模式

优点:

缺点:

运用场景

总结

代理模式是一种常用的结构型设计模式,它可以让我们通过一个代理对象来间接访问一个真实对象,从而实现对目标对象的功能扩展或保护。代理模式有三个主要角色:抽象主题、真实主题和代理主题。代理模式有多种类型,例如静态代理、动态代理、远程代理、虚拟代理等。代理模式有自己的优缺点,使用时需要根据具体的场景和需求来选择合适的类型和方式。

上一篇 下一篇

猜你喜欢

热点阅读