11 设计模式之代理模式(送资料案例)

一、什么是代理模式?

在现实生活中,我们常常遇到这样的场景:由于某些原因,我们可能无法亲自完成某个任务,便会委托他人代为执行。在设计模式中,代理模式 就是用来解决这种"委托"问题的,它允许一个对象通过代理对象来控制对另一个对象的访问。

今天我们就通过一个简单的例子来讲解代理模式的应用场景:小明委托小亮送资料给老师。

代理模式(Proxy Pattern)是一种结构型设计模式,它通过引入代理对象来控制对某个对象的访问。代理对象可以在访问实际对象之前或之后进行一些额外的操作。代理模式可以帮助我们在不改变原有对象的情况下,为对象提供附加功能。

1.代理模式的角色

  • **主题接口(Object):**存放任务的抽象接口
  • 真实对象(Real Object):真正的执行任务的对象。
  • 代理对象(Proxy):代理类,代替真实对象执行任务,并在必要时执行一些额外的操作。
  • 委托者(Client):请求执行任务的对象,通常由客户端调用代理类来完成任务。

二、代理模式应用

假设小明有一份重要的资料需要交给老师,但由于某些原因,小明不能亲自送过去。于是,小明委托了小亮来代为送资料。

  • 小明:需要将资料交给老师,无法亲自送达。
  • 小亮:代理小明去送资料。
  • 老师:实际接收资料的人。

在这个例子中,小明通过小亮来"代理"完成送资料的任务,而小亮在送资料之前可以做一些额外的操作(例如确认资料是否完整)。代理模式正是通过这种方式来实现任务的委托。


三、代理模式的类设计

我们将这个场景通过代码实现。下面是我们用 Java 语言实现的类设计。

1. 资料类 Document

资料类表示需要交给老师的资料,包含资料名称和内容。

java 复制代码
public class Document {
    private String name;  // 资料名称
    private String content; // 资料内容

    public Document(String name, String content) {
        this.name = name;
        this.content = content;
    }

    public String getName() {
        return name;
    }

    public String getContent() {
        return content;
    }

    @Override
    public String toString() {
        return "资料名称: " + name + ", 内容: " + content;
    }
}

2. 送资料接口 Delivery

定义一个接口 Delivery,所有的送资料类都需要实现这个接口。

java 复制代码
public interface Delivery {
    void deliver(Document document);  // 送资料的行为
}

3. 实际送资料的类 DeliveryService

DeliveryService 类实现了 Delivery 接口,并负责实际的送资料操作。

java 复制代码
public class DeliveryService implements Delivery {
    @Override
    public void deliver(Document document) {
        System.out.println("送资料给老师: " + document);
    }
}

4. 代理类 DeliveryProxy

DeliveryProxy 类作为代理,负责在送资料之前进行一些额外的操作,比如确认资料是否完好。如果资料没有问题,代理会将任务委托给 DeliveryService

java 复制代码
public class DeliveryProxy implements Delivery {
    private DeliveryService deliveryService;  // 代理类持有一个 `DeliveryService` 的引用

    public DeliveryProxy() {
        this.deliveryService = new DeliveryService();  // 实例化实际的送资料服务
    }

    @Override
    public void deliver(Document document) {
        System.out.println("代理检查:确认资料是否完好...");
        // 代理类可以做一些额外的操作,比如验证资料
        if (document.getContent().length() > 0) {
            // 资料无误,代理继续执行送资料的任务
            System.out.println("代理:资料确认无误,开始送资料...");
            deliveryService.deliver(document);  // 委托给实际送资料服务
        } else {
            System.out.println("代理:资料有问题,无法送达!");
        }
    }
}

5. 测试类 ProxyPatternTest

最后,我们编写一个测试类来验证代理模式的应用。

java 复制代码
public class ProxyPatternTest {
    public static void main(String[] args) {
        // 模拟小明的资料
        Document document = new Document("Java 教学资料", "内容:Java设计模式");

        // 小明委托小亮送资料
        Delivery proxy = new DeliveryProxy();
        proxy.deliver(document);

        // 假设资料为空的情况
        Document brokenDocument = new Document("错误的资料", "");
        proxy.deliver(brokenDocument);  // 代理会检查并拒绝送达
    }
}

四、代理模式的执行流程

在测试中,我们通过 ProxyPatternTest 类模拟了两次送资料的过程。

1.第一次送资料

  • 代理类首先会检查资料是否完整。
  • 如果资料没有问题,代理会将任务交给 DeliveryService 类来执行实际的送资料操作。

2.第二次送资料

  • 代理类再次检查资料是否完整。如果资料为空,代理会直接拒绝送达。

3.执行输出:

复制代码
代理检查:确认资料是否完好...
代理:资料确认无误,开始送资料...
送资料给老师: 资料名称: Java 教学资料, 内容: 内容:Java设计模式

代理检查:确认资料是否完好...
代理:资料有问题,无法送达!

五、代理模式的优势与应用场景

1.代理模式的优势

  1. 增强功能:通过代理对象可以在不修改原始对象的情况下,增强其功能。
  2. 延迟加载:代理对象可以控制是否要真正加载或执行某些操作,节省资源。
  3. 灵活控制:代理对象可以控制真实对象的访问,进行权限管理或其他额外操作。

2.应用场景

  • 延迟加载:例如图片、视频的加载,只有在需要时才加载资源。
  • 虚拟代理:例如,显示大量数据时,只在用户滚动到相应位置时才加载数据。
  • 远程代理:在分布式系统中,代理类可以作为客户端与远程服务之间的中介。
  • 保护代理:代理类可以控制对真实对象的访问,例如权限控制、身份认证等。

六、总结

代理模式是一种结构型设计模式,它通过引入代理对象来控制对真实对象的访问。在我们的例子中,小明委托小亮送资料给老师,小亮作为代理类,在送资料之前可以做一些额外的操作,比如确认资料的完整性。通过代理模式,我们能够增强任务的功能而不修改实际执行任务的对象。

代理模式非常适合需要控制访问、增强功能或延迟加载的场景。如果你在项目中有类似需求,可以考虑使用代理模式。


希望这篇博客能够帮助你更好地理解代理模式的应用!如果有任何问题,欢迎随时在评论区留言或私信我。

相关推荐
闻闻不会编程6 分钟前
704. 二分查找 (力扣)
数据结构·算法·leetcode
AndrewHZ12 分钟前
【图像处理基石】立体匹配的经典算法有哪些?
图像处理·算法·计算机视觉·滤波·模式识别·立体匹配
AndrewHZ16 分钟前
【图像处理入门】4. 图像增强技术——对比度与亮度的魔法调节
图像处理·算法·计算机视觉·几何变换·图像增强·模式识别
哆啦A梦的口袋呀20 分钟前
基于Python学习《Head First设计模式》第三章 装饰者模式
python·学习·设计模式
哆啦A梦的口袋呀22 分钟前
基于Python学习《Head First设计模式》第五章 单件模式
python·学习·设计模式
天天摸鱼的java工程师22 分钟前
CTO新项目直接上MySQL 8.0,老系统仍是5.7
java·后端·mysql
bxlj_jcj24 分钟前
解锁Java多级缓存:性能飞升的秘密武器
java·缓存·面试·架构
未来并未来26 分钟前
Redis 缓存问题及其解决方案
java·redis·缓存
快乐肚皮1 小时前
MySQL集群模式详解:架构、优缺点与生产环境选型指南
java·mysql
不二狗1 小时前
每日算法 -【Swift 算法】查找字符串数组中的最长公共前缀
开发语言·算法·swift