【设计模式|结构型】代理模式(Proxy Pattern)

背景

代理模式和适配器模式有什么区别?下面用两个示例来说明

适配器模式:假设你在家里有一个电源插座,但是你的笔记本电脑的电源线的插头是美国标准的,无法直接插到家里的电源插座中。这时,你可以使用一个适配器来解决这个问题。

代理模式:假设你家里有一个保姆,你不想让保姆直接接触你的贵重物品,但是你需要让保姆帮你照顾这些物品。这时,你可以使用一个代理来解决这个问题。

概述

代理模式是一种结构型设计模式,它使得代理对象可以控制对实际对象的访问。在代理模式中,代理对象通过持有对实际对象的引用,来代替实际对象进行操作。

代理对象对客户端隐藏了实际对象的细节,并可以在调用实际对象之前或之后执行一些额外的操作,如权限验证、缓存数据、对请求进行转发等。

示例一

以保姆保管贵重物品为例。

定义一个 Nanny 接口,表示保姆的行为:

public interface Nanny {
    void takeCareOfValuables();
}

创建一个具体的 NannyImpl 类来实现 Nanny 接口,表示真正的保姆:

public class NannyImpl implements Nanny {
    @Override
    public void takeCareOfValuables() {
        System.out.println("保姆正在照顾贵重物品");
    }
}

创建一个代理类 NannyProxy 来控制对保姆的访问,并在访问时添加额外的逻辑。例如,我们可以在保姆访问贵重物品之前,先记录下保姆的行为:

public class NannyProxy implements Nanny {
    private Nanny nanny;

    public NannyProxy(Nanny nanny) {
        this.nanny = nanny;
    }

    @Override
    public void takeCareOfValuables() {
        System.out.println("代理保姆正在记录行为");
        nanny.takeCareOfValuables();
    }
}

在客户端代码中使用代理模式来控制对保姆的访问:

public class Main {
    public static void main(String[] args) {
        // 创建真正的保姆对象
        Nanny nanny = new NannyImpl();

        // 创建代理保姆对象
        Nanny proxy = new NannyProxy(nanny);

        // 通过代理保姆来访问贵重物品
        proxy.takeCareOfValuables();
    }
}

运行结果:

代理保姆正在记录行为
保姆正在照顾贵重物品

示例二

假设我们有一个远程文件下载器,负责从远程服务器下载文件。为了增强下载器功能,我们可以使用代理模式来创建一个下载器的代理。

首先定义一个远程文件下载器的接口:

public interface FileDownloader {
    void download(String url);
}

然后实现实际的远程文件下载器:

public class FileDownloaderImpl implements FileDownloader {
    @Override
    public void download(String url) {
        // 实际的下载逻辑,省略
        System.out.println("Downloading file from " + url);
    }
}

接下来定义一个文件下载代理:

public class FileDownloaderProxy implements FileDownloader {
    private FileDownloaderImpl fileDownloader;

    @Override
    public void download(String url) {
        // 在下载文件之前进行一些额外的操作
        System.out.println("Before downloading file");
        
        // 延迟加载实际文件下载器
        if (fileDownloader == null) {
            fileDownloader = new FileDownloaderImpl();
        }
        
        // 调用实际文件下载器的方法
        fileDownloader.download(url);
        
        // 在下载文件之后进行一些额外的操作
        System.out.println("After downloading file");
    }
}

客户端代码可以通过文件下载代理来下载文件,而无需直接访问实际下载器:

public class Client {
    public static void main(String[] args) {
        FileDownloader downloader = new FileDownloaderProxy();
        downloader.download("https://example.com/file.txt");
    }
}

运行结果:

Before downloading file
Downloading file from https://example.com/file.txt
After downloading file 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

脱发的老袁

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

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

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

打赏作者

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

抵扣说明:

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

余额充值