结构型(一) - 代理模式

一、概念

代理模式(Proxy Pattern):它在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加新功能。

使用场景:代理模式最常用的一个应用场景就是,在业务系统中开发一些非功能性需求,比如:监控、统计、鉴权、限流、事务、幂等、日志。我们将这些附加功能与业务功能解耦,放到代理类中统一处理,让程序员只需要关注业务方面的开发。

二、实现

  • 静态代理

借鉴下面参考文章VPN的例子,实现了静态代理:

1、定义网站接口

java 复制代码
public interface Website {
    void processRequest();
    void saveHistory();
}

2、实现网站Baidu实例

java 复制代码
public class Baidu implements Website{
    @Override
    public void processRequest() {
        System.out.println("正在访问Baidu");
    }

    @Override
    public void saveHistory() {
        System.out.println("保存访问Baidu记录");
    }
}

3、访问baidu网站

java 复制代码
public class Client {
    public static void main(String[] args) {
        Baidu baidu = new Baidu();
        baidu.processRequest();
        baidu.saveHistory();
    }
}

4、访问结果:

5、实现网站Youtube实例

java 复制代码
public class Youtube implements Website{
    @Override
    public void processRequest() {
        System.out.println("正在访问Youtube");
    }

    @Override
    public void saveHistory() {
        System.out.println("保存访问Youtube记录");
    }
}

6、如果我们要访问国外的网站Youtube,Facebook等,直接访问是不行的,我们就需要加一个vpn,登录vpn后可正常访问。所以我们需要在访问Youtube这些网站前加上vpn登录校验功能,如果未登录先登录vpn在去访问。但是如果每个网站的每个方法前挨个加判断太麻烦了,所以我们写一个代理类,统一给这些国外的网站加上登录校验功能。

java 复制代码
public class VPN implements Website {
    private Website proxiedWebsite;
    public VPN (Website wb){
        this.proxiedWebsite = wb;
    }

    @Override
    public void processRequest() {
        loginVpn();
        proxiedWebsite.processRequest();
    }

    @Override
    public void saveHistory() {
        loginVpn();
        proxiedWebsite.saveHistory();
    }

    private void loginVpn() {
        System.out.println("校验vpn登录状态,已登录");
    }
}

总结:个人理解,vpn这里相当于一个网站代理,我们把要访问的网站给代理类,代理类会处理vpn登录等判断并帮我们访问我们需要的网站。vpn登录功能相对于之前的网站访问及网站历史记录等网站业务功能是相对独立的,所以直接加在原来代码中不合理,因此该功能抽出来用代理类去处理。

7、访问Youtube :

java 复制代码
public class Client {
    public static void main(String[] args) {
        //Baidu baidu = new Baidu();
        //baidu.processRequest();
        
        //直接访问
        //Youtube youtube = new Youtube();
        //youtube.processRequest();
        //youtube.saveHistory();

        //代理访问
        Website youtube = new VPN(new Youtube());
        youtube.processRequest();
        youtube.saveHistory();
    }
}

8、运行结果:

总结:从上面的例子可以看出,VPN需要实现Website接口,代理类需要把实现类的方法都实现一遍。后面增加登录校验功能,就需要在每个实现方法中都加一遍。

  • 动态代理

动态代理就是我们不事先为每个原始类编写代理类,而是在运行的时候,动态地创建原始类对应的代理类,然后在系统中用代理类替换掉原始类。

代码实现:

1、动态代理实现,先实现接口InvocationHandler,然后通过Proxy类的newProxyInstance()方法创建这个代理。被代理类方法通过反射调用invoke执行,我们在每次执行前加一个vpn登录校验。

java 复制代码
public class WebsiteHandler implements InvocationHandler {
    private Website proxiedObject;

    public WebsiteHandler(Website wb) {
        this.proxiedObject = wb;
    }

    public Website getProxyInstance() {
        return (Website) Proxy.newProxyInstance(this.getClass().getClassLoader()
                , proxiedObject.getClass().getInterfaces(), this);
    }

   @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        loginVpn();
        return method.invoke(proxiedObject, args);
    }

    private void loginVpn() {
        System.out.println("校验vpn登录状态,已登录");
    }
}

2、代理实现和调用

java 复制代码
public class Client {
    public static void main(String[] args) {
        //Baidu baidu = new Baidu();
        //baidu.processRequest();
        
        Youtube youtube = new Youtube();
        WebsiteHandler websiteHandler = new WebsiteHandler(youtube);
        Website website = websiteHandler.getProxyInstance();
        website.processRequest();
        website.saveHistory();
    }
}

3、运行结果

总结:这里我们没有去写一个代理类,而是交给Proxy去生成,然后在InvocationHandler的invoke方法去实际执行。这个代理类,是在运行阶段生成的,无需事前写好。从上面例子可以看到,如果加功能的话在反射调用的时候统一加上就行,无需像静态代理一样在每个实现方法中都加一遍。

参考文章:
设计模式之代理模式

相关推荐
geovindu20 小时前
rust: Semaphore Pattern
开发语言·后端·设计模式·rust·代理模式·企业级信号量模式·同步型模式
一切皆是因缘际会2 天前
最优 控制
代理模式
\光辉岁月/7 天前
3.spring5-AOP
spring·代理模式·aop·spring5
AI_Cloud_推荐12 天前
DeepSeek-V4-Pro 的 4.5 和 12:不是加价,是同名不同版本
阿里云·语言模型·代理模式·ai编程·百度云
devilnumber16 天前
Java 代理模式(简单理解回顾)
java·开发语言·代理模式
驭渊的小故事18 天前
软件工程概念篇:需求、开发模型与测试模型全解析
人工智能·代理模式
king135987455018 天前
Gemini 4 Argon API 接入与迁移:模型参数、Token 价格和 Agent 测试方案
大模型·代理模式·ai agent·gemini
YumiProxy22 天前
代理IP自动切换避坑指南:会话保持、请求头与错误处理实战
网络·网络协议·tcp/ip·代理模式·ip
-dzk-24 天前
【动态规划】LC 416.分割等和子集
算法·动态规划·代理模式
步行cgn1 个月前
GoF 代理模式详解
代理模式