结构型(一) - 代理模式

一、概念

代理模式(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去生成,然后在InvocationHandlerinvoke方法去实际执行。这个代理类,是在运行阶段生成的,无需事前写好。从上面例子可以看到,如果加功能的话在反射调用的时候统一加上就行,无需像静态代理一样在每个实现方法中都加一遍。

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

相关推荐
Auc2420 小时前
OJ判题系统第4期之判题机模块架构——设计思路、实现步骤、代码实现(工厂模式、代理模式的实践)
java·spring cloud·log4j·mybatis·代理模式·工厂模式
Yang三少喜欢撸铁2 天前
【阿里云免费领取域名以及ssl证书,通过Nginx反向代理web服务】
nginx·阿里云·代理模式·ssl
Blurpath3 天前
什么是静态住宅IP?为什么静态住宅IP能提高注册通过率?
网络·代理模式·ip代理·住宅ip
python算法(魔法师版)3 天前
JavaScript性能优化实战,从理论到落地的全面指南
开发语言·性能优化·前端框架·代理模式
常某某的好奇心6 天前
代理模式(Proxy Pattern)
代理模式
彬彬醤6 天前
全局网络:重构数字时代的连接范式
运维·服务器·网络·数据库·重构·代理模式
菜鸟破茧计划9 天前
穿越数据森林与网络迷宫:树与图上动态规划实战指南
网络·动态规划·代理模式
yy鹈鹕灌顶11 天前
动态规划算法精解(Java实现):从入门到精通
代理模式
帝锦_li12 天前
Java进阶--设计模式
观察者模式·单例模式·代理模式·抽象工厂模式·适配器模式·原型模式
工业甲酰苯胺15 天前
用远程代理模式轻松实现远程服务调用,打开编程新大门
代理模式