代理模式【Proxy Pattern】,什么是代理模式?主要角色?代理模式分类?优缺点?应用场景?代理模式实现?

目录


设计模式专栏目录(点击进入…)



什么是代理模式?

代理模式(Proxy Pattern)是一种结构型设计模式,它通过为其他对象提供一种代理以控制对这个对象的访问。代理模式主要用于在不修改原对象的前提下,给原对象的功能添加控制、增强或简化客户端的访问。


代理模式的主要角色

(1)抽象主题(Subject)

定义代理和真实对象的共同接口,以便客户端可以通过代理对象或真实对象访问同一组方法。

(2)真实主题(Real Subject)

真正实现业务逻辑的对象。代理对象通过调用真实对象来完成具体的功能。

(3)代理(Proxy)

控制对真实对象的访问,可以在调用真实对象的方法前后添加额外的逻辑,比如权限验证、延迟加载、日志记录等。


代理模式分类

(1)静态代理

代理类和目标类在编译期间就已经确定,代理类通常由程序员手动编写。

(2)动态代理

代理类在运行时动态生成,通过反射机制实现。Java 中的动态代理(如 JDK 动态代理和 CGLIB 动态代理)就是一种常见实现。


代理模式优缺点

优点

(1)控制对真实对象的访问

代理模式能够在不直接访问真实对象的情况下,通过代理对象控制对真实对象的访问。这对于权限控制、资源管理等场景非常有用。

(2)增强对象的功能

代理可以在不修改原有代码的前提下增强真实对象的功能。例如,增加日志记录、监控、缓存、延迟加载等,扩展了对象的行为。

(3)延迟初始化

通过虚拟代理,可以实现真实对象的延迟加载,即当客户端真正需要时才创建该对象,节省了系统资源。

(4)支持远程访问

远程代理模式能够将本地调用代理到远程对象上,实现透明的网络调用,使得分布式系统的实现更加简单。

(5)符合开闭原则

代理模式允许在不修改真实对象代码的情况下添加额外功能,遵循了软件设计的开闭原则(对扩展开放,对修改关闭)。

缺点

(1)增加了系统复杂度

使用代理模式时,系统需要引入一个额外的代理对象,增加了类的数量和系统的复杂性,特别是在动态代理的场景下,调试和排查问题会更麻烦。

(2)性能开销

由于代理模式引入了额外的层次和方法调用,这在某些场景下会导致性能开销。例如,频繁的远程代理调用可能会增加网络延迟,或者动态代理的反射机制会带来一定的性能损耗。

(3)可能滥用代理

代理模式非常灵活,但不适合在所有场景中使用。如果滥用代理模式,会导致系统结构变得复杂,难以维护。代理类的引入应当有明确的目的和需求。

(4)调试难度增大

使用代理模式后,方法调用链条变长,特别是动态代理的使用,可能会使调试、定位问题的难度增加,因为代理类隐藏了对真实对象的直接调用关系。


代理模式应用场景

(1)远程代理

代理远程的对象,通过代理对象来调用远程服务。

(2)虚拟代理

当对象的创建开销较大时,使用代理延迟对象的创建。

(3)保护代理

在调用对象的方法时进行权限控制,确保客户端具有访问权限。

(4)缓存代理

为开销较大的操作提供临时存储,以提高性能。

(5)日志代理

在调用对象的方法时,自动记录日志。


代理模式实现

什么是代理模式呢?
我很忙,忙的没空理你,那你要找我呢就先找我的代理人吧,那代理人总要知道被代理人能做哪些事情不能做哪些事情吧,那就是两个人具备同一个接口,代理人虽然不能干活,但是被代理的人能干活呀。
比如:西门庆想找潘金莲,那潘金莲不好意思答复呀,咋办,找那个王婆做代理,表现在程序上时这样的:

在这里插入图片描述

1、定义一种类型的女人(抽象主题,Subject)

package com.uhhe.common.design.proxy;

/**
 * 定义一种类型的女人,王婆和潘金莲都属于这个类型的女人
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 9:38
 */
public interface KindWomen {

    /**
     * 这种类型的女人能做什么事情呢? 抛媚眼
     */
    void makeEyesWithMan();

    /**
     * happy what? You know that!
     */
    void happyWithMan();

}

2、定义潘金莲(真实主题,Real Subject)

package com.uhhe.common.design.proxy;

/**
 * 定义一个潘金莲
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 9:39
 */
public class PanJinLian implements KindWomen {

    @Override
    public void happyWithMan() {
        System.out.println("潘金莲在.....");
    }

    @Override
    public void makeEyesWithMan() {
        System.out.println("潘金莲抛媚眼");
    }

}

3、定义王婆(代理,Proxy)

package com.uhhe.common.design.proxy;

/**
 * 王婆这个人老聪明了,她太老了,是个男人都看不上,但是她有智慧有经验呀,她作为一类女人的代理!
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 9:40
 */
public class WangPo implements KindWomen {

    private final KindWomen kindWomen;

    public WangPo() {
        // 默认是潘金莲的代理
        this.kindWomen = new PanJinLian();
    }

    /**
     * 她可以是KindWomen的任何一个女人的代理,只要你是这一类型
     *
     * @param kindWomen 一类女人
     */
    public WangPo(KindWomen kindWomen) {
        this.kindWomen = kindWomen;
    }

    @Override
    public void happyWithMan() {
        // 自己老了,可以让年轻的代替
        this.kindWomen.happyWithMan();
    }

    @Override
    public void makeEyesWithMan() {
        // 王婆这么大年龄了,谁看她抛媚眼?
        this.kindWomen.makeEyesWithMan();
    }

}

4、定义西门庆

package com.uhhe.common.design.proxy;

/**
 * 定义一个西门庆
 *
 * @author nizhihao
 * @version 1.0.0
 * @date 2023/2/27 9:42
 */
public class XiMenQing {

    /**
     * 代理模式【Proxy Pattern】
     * <p>
     * 比如:西门庆找潘金莲,那潘金莲不好意思答复呀,咋办,找那个王婆做代理
     * <p>
     * 水浒里是这样写的:西门庆被潘金莲用竹竿敲了一下难道,痴迷了,被王婆看到了, 就开始撮合两人好事
     * 王婆作为潘金莲的代理人收了不少好处费,那我们假设一下:如果没有王婆在中间牵线,这两个的能成吗?难说的很!
     * <p>
     * 代理模式主要使用了 Java 的多态,干活的是被代理类,代理类主要是接活
     * 你让我干活,好,我交给幕后的类去干,你满意就成,那怎么知道被代理类能不能干呢?
     * 同根就成,大家知根知底,你能做啥,我能做啥都清楚的很(同一个接口)
     */
    public static void main(String[] args) {
        // 把王婆叫出来
        WangPo wangPo = new WangPo();
        // 然后西门庆就说,我要和潘金莲happy,然后王婆就安排了西门庆丢筷子的那出戏
        // 看到没,虽然表面上是王婆,实际上是潘金莲
        wangPo.makeEyesWithMan();
        wangPo.happyWithMan();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未禾

您的支持是我最宝贵的财富!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值