7、设计模式之代理模式

开始之前

本章节是一个系列,里面用的的代码实例都是连贯的。在实现某一种设计模式时,为了减少代码篇幅,前面博客出现model类(仅限公用的model类,比如compute、CPU、Mem、Disk等纯对象类)不会重复出现,读者在阅读某一篇博客时,如果发现突然出现了一个新的model类,在本片博客中没有其定义,可以往前面的博客翻一下!

最后,当本系列更新完成后,我会整个的代码完整贴出来,提供下载链接!

代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

介绍

意图: 为其他对象提供一种代理以控制对这个对象的访问。

主要解决: 在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

如何解决: 增加中间层。

应用实例:

1、Windows 里面的快捷方式。

2、买火车票不一定在火车站买,也可以去代售点。

3、一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。

4、spring aop。

优点: 1、职责清晰。 2、高扩展性。 3、智能化。

缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

使用场景:

按职责来划分,通常有以下使用场景:

1、远程代理。
远程代理主要处理不在本地计算机的对象。代理对象扮演着远程对象的本地代表,所有对远程对象的操作都通过代理对象完成。webservice、EJB、dubbo等分布式技术。

2、虚拟代理。
虚拟代理用于处理大规模资源的对象,比如大图像或者网络资源。在真正需要时,再去创建或加载这个资源。

3、Copy-on-Write 代理。
它是虚拟代理的一种,把克隆操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。

4、保护(Protect or Access)代理。
保护(Protect or Access)代理用于控制真实对象的访问权限,只有通过安全检查的请求才能访问真实对象。比如,有些对象有对其访问和操作的权限限制,我们可以把权限的处理逻辑放到代理中。

5、Cache代理。
为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。从而可以避免某些方法的重复执行,优化系统性能。

6、防火墙(Firewall)代理。

7、同步化(Synchronization)代理。
是一种用于在多线程环境中保持对象状态一致性的机制。它通常用于懒加载或延迟初始化的上下文中。在这种代理中,方法调用会被转发到实际的对象,并通过某种同步机制确保线程安全。

8、智能引用(Smart Reference)代理。
智能指引是为一个对象提供一种代理,并在一些特定的情况下选择提供一种“智能”的操作方式。比如引用计数,如果一个对象进行指向操作,其引用计数+1;如果进行解引用操作,其引用计数-1,等到引用计数为0时,可以自动回收对象。

注意事项:

  • 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
  • 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。

主要涉及到以下几个核心角色:

  • 抽象主题(Subject):

    • 定义了真实主题和代理主题的共同接口,这样在任何使用真实主题的地方都可以使用代理主题。
  • 真实主题(Real Subject):

    • 实现了抽象主题接口,是代理对象所代表的真实对象。客户端直接访问真实主题,但在某些情况下,可以通过代理主题来间接访问。
  • 代理(Proxy):

    • 实现了抽象主题接口,并持有对真实主题的引用。代理主题通常在真实主题的基础上提供一些额外的功能,例如延迟加载、权限控制、日志记录等。

代码实现

同步代理

现在模拟一个IO

public interface FileIO {

    int read();

    int write();
}

public class FileIOImpl implements FileIO{

    private int size;

    @Override
    public int read() {
        size--;
        System.out.println("read size:"+size);
        return size;
    }

    @Override
    public int write() {
        size++;
        System.out.println("write size:"+size);
        return size;
    }
}

如果直接进行FileIO进行访问,那么多线程情况下,size的访问是不安全的。

这个是需要一个代理实现同步作用的同时,原来的代码也不需要改动。

public class SyncFileIO {
    private FileIO fileIO;

    public SyncFileIO(FileIO fileIO)
    {
        this.fileIO = fileIO;
    }

    public synchronized int read()
    {
        return fileIO.read();
    }

    public synchronized int write()
    {
        return fileIO.write();
    }
}

public class Client {
    public static void main(String[] args) {
        FileIO fileIO = new FileIOImpl();
        //通过syncfileIO代理fileIO,保证线程安全
        SyncFileIO syncFileIO = new SyncFileIO(fileIO);
        syncFileIO.write();
        syncFileIO.read();
    }
}

保护代理(也叫安全代理或者访问控制代理)

保护代理在spring框架中用的比较多,假设现在有一个请求进来,在请求处理之前需要判断这个请求是否合法

public interface Request {
    void request();
}

public class GetRequest implements Request {

    @Override
    public void request(){
        System.out.println("get request");
    }
}

没有代理的情况下,就需要修改GetRequest这个类的处理逻辑,通过代理就可以不需要改动GetRequest这个类的处理逻辑,

public class RequestProxy {

    Request request;

    public RequestProxy(Request request) {
        this.request = request;
    }

    private void beforeReques(){
        System.out.println("proxy before");
    }

    public void request(){
        beforeReques();
        request.request();
        afterRequest();
    }

    public void afterRequest(){
        System.out.println("proxy after");
    }
}

public class Client {
    public static void main(String[] args) {
        Request request = new GetRequest();
        RequestProxy requestProxy = new RequestProxy(request);
        requestProxy.request();
    }
}
  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

风吹千里

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值