【愚公系列】2023年10月 二十三种设计模式(十二)-代理模式(Proxy Pattern)

举报
愚公搬代码 发表于 2021/12/04 18:49:17 2021/12/04
【摘要】 设计模式(Design Pattern)是软件开发领域的宝贵经验,是多人反复借鉴和广泛应用的代码设计指导。它们是一系列经过分类和归纳的代码组织方法,旨在实现可重用性、可维护性和可理解性。使用设计模式,我们能够编写高质量的代码,使其更易于他人理解,并提供了代码可靠性的保证。

🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏

🚀前言

设计模式(Design Pattern)是软件开发领域的宝贵经验,是多人反复借鉴和广泛应用的代码设计指导。它们是一系列经过分类和归纳的代码组织方法,旨在实现可重用性、可维护性和可理解性。使用设计模式,我们能够编写高质量的代码,使其更易于他人理解,并提供了代码可靠性的保证。

毫无疑问,设计模式对个人、团队和整个系统都带来了显著的益处。它们将代码开发提升到工程化水平,为软件工程构建提供了坚实的基础,就如同大厦的一块块精巧的砖石一样。在项目中明智地应用设计模式可以完美地解决各种复杂问题。每种设计模式都有相应的原理和最佳实践,它们描述了我们日常开发中不断遇到的问题,以及这些问题的核心解决方法。正是因为这种实用性和通用性,设计模式才能在软件开发中广泛地得以应用。设计模式是构建稳健、可扩展和可维护软件的关键工具,为开发者们提供了解决问题的智慧和指导。

🚀一、代理模式(Proxy Pattern)

代理模式是一种结构型设计模式,它为其他对象提供了一种代理,以控制对目标对象的访问。这种模式的出现是因为在某些情况下,直接引用一个对象并不合适或不可行,而代理对象可以充当客户端和目标对象之间的中介,提供了更多的控制和灵活性。

代理模式通常在以下情况下使用:

  1. 远程代理:当目标对象位于远程服务器上时,可以使用远程代理作为客户端和服务器之间的通信媒介,以便客户端可以像访问本地对象一样访问远程对象。

  2. 虚拟代理:在需要延迟加载或初始化开销较大的对象时,虚拟代理可以在必要时才真正创建目标对象,从而提高性能和减少资源消耗。

  3. 保护代理:保护代理用于控制客户端对目标对象的访问权限。它可以根据访问者的身份或权限决定是否允许访问目标对象。

  4. 缓存代理:缓存代理在需要对某些计算结果或数据进行缓存时使用。它可以缓存已经计算过的结果,以避免重复计算,提高性能。

  5. 智能引用:智能引用代理可以在目标对象被引用时执行额外的操作,例如引用计数、记录引用次数等。

代理模式允许我们在不改变原有代码逻辑的情况下,通过引入代理对象来管理和控制对目标对象的访问。这提供了更多的灵活性和可维护性,使我们能够更好地管理对象之间的交互和访问权限。

🚀二、使用步骤

🔎1.角色

🦋1.1 抽象主题(Subject)

在代理模式(Proxy Pattern)中,抽象主题(Subject)是一个关键的概念,它扮演了代理对象和真实对象之间的桥梁角色,具有以下作用:

  1. 定义接口:抽象主题定义了真实主题(Real Subject)和代理对象(Proxy)都必须实现的接口或抽象类。这个接口规定了客户端可以访问的方法。

  2. 解耦客户端和真实对象:抽象主题将客户端与真实对象解耦。客户端不直接引用真实对象,而是通过抽象主题来访问。这样可以随时更换代理对象,而不需要修改客户端代码。

  3. 提供通用接口:抽象主题为真实对象和代理对象提供了一个共同的接口,这意味着客户端可以使用相同的方式来访问真实对象和代理对象。客户端不需要关心代理对象是否在起作用。

  4. 控制访问权限:抽象主题可以用于控制客户端对真实对象的访问权限。代理对象可以在调用真实对象之前或之后执行一些额外的逻辑,例如权限验证、延迟加载等。

  5. 实现懒加载:抽象主题可以用于实现懒加载(Lazy Loading),即只有在真正需要时才创建和初始化真实对象。这可以节省资源和提高性能。

  6. 实现缓存:抽象主题还可以用于实现缓存。代理对象可以在请求发生时检查是否已经有一个缓存的真实对象实例,如果有,则直接返回缓存的对象,而不需要重新创建。

抽象主题在代理模式中充当了接口定义和客户端与代理对象之间的中介角色,它提供了一种灵活的方式来控制和管理对真实对象的访问,并允许在不改变客户端代码的情况下引入代理对象。这有助于提高代码的可维护性、扩展性和灵活性。

🦋1.2 代理主题(Proxy)

代理模式(Proxy Pattern)中的代理主题(Proxy)是一个重要的概念,它充当了客户端和真实主题(Real Subject)之间的中介或代理角色,具有以下作用:

  1. 控制访问:代理主题用于控制客户端对真实主题的访问。它可以充当门卫的角色,根据需要允许或拒绝客户端的请求。这种控制访问的能力可以用于实现权限控制或安全性控制。

  2. 延迟加载:代理主题可以延迟加载真实主题,也就是只有在需要的时候才创建和初始化真实主题对象。这种延迟加载的机制可以节省资源和提高性能,特别是当真实主题的创建成本较高时。

  3. 实现虚拟代理:代理主题可以用于实现虚拟代理。虚拟代理是一种延迟加载的代理,它在需要时才加载真实主题。这对于管理大量对象中的某些复杂或昂贵的对象非常有用。

  4. 实现远程代理:代理主题可以用于实现远程代理。远程代理允许客户端通过代理对象访问位于远程服务器上的真实对象,这在分布式系统中非常常见。

  5. 实现缓存:代理主题可以用于实现缓存。代理可以维护已经访问过的真实对象的副本,并在需要时返回缓存的对象,从而提高性能。

  6. 记录日志:代理主题可以用于记录日志或跟踪客户端对真实对象的请求。这对于调试和监控应用程序非常有帮助。

  7. 实现智能引用:代理主题可以用于实现智能引用。智能引用代理可以记录对真实对象的引用次数,以便在不再被引用时释放资源。

代理主题在代理模式中充当了客户端与真实主题之间的中介,可以控制和扩展对真实对象的访问方式,提供了一种更加灵活和可管理的方式来管理对象的访问和行为。这使得代理模式在许多不同的应用场景

🦋1.3 真实主题(Real Subject)

在代理模式(Proxy Pattern)中,真实主题(Real Subject)是一个核心概念,它代表了被代理的真实对象,具有以下作用:

  1. 封装真实业务逻辑:真实主题封装了实际的业务逻辑,是代理模式中的关键实体。它包含了客户端所关心的功能或数据,但通常具有一定的复杂性。

  2. 提供具体功能:真实主题负责执行客户端请求的具体功能。这意味着它实际上执行了代理模式的核心任务,客户端通过代理间接访问真实主题来实现某项功能。

  3. 可能是高开销的对象:真实主题可能是创建和初始化开销较高的对象,或者需要特殊的资源或权限来访问。代理模式的一个目标是在需要时才创建和初始化真实主题,以减少资源浪费。

  4. 可能需要保护:有时真实主题需要受到保护,不希望客户端直接访问。代理模式可以提供额外的安全性层,确保只有经过代理才能访问真实主题。

  5. 可替换性:代理模式允许在不修改客户端代码的情况下替换真实主题。这对于实现不同版本或实现的切换非常有用。

  6. 实现抽象主题接口:真实主题必须实现抽象主题(Subject)定义的接口或抽象类。这确保了代理和真实主题具有相同的接口,使得客户端可以无差异地使用它们。

真实主题是代理模式的核心组成部分,它代表了真正的业务逻辑或对象,通过代理来提供访问和控制的方式。真实主题的存在使得代理模式能够解决许多不同的问题,包括延迟加载、权限控制、性能优化等。客户端通过代理对象间接访问真实主题,实现了对真实主题的控制和封装。

🔎2.示例

在这里插入图片描述

命名空间ProxyPattern中包含Employee员工类充当抽象主题,Leader领导类充当代理主题,Staff普通员工类充当真实主题。本案例尝试通过员工采购一批桌子来介绍领导是如何通过使用普通员工作为自己的代理为公司采购商品的。

public abstract class Employee {

    public abstract void Purchase(string goods);

    protected virtual void OnPurchasing() {
        Console.WriteLine("Employee.OnPurchasing()");
    }

    protected virtual void OnPurchased() {
        Console.WriteLine("Employee.OnPurchased()");
    }

}

员工类Employee。

public class Staff : Employee {
 
    public override void Purchase(string goods) {
        OnPurchasing();
        Console.WriteLine($"Purchase some {goods}s!");
        OnPurchased();
    }
 
    protected override void OnPurchasing() {
        Console.WriteLine("Staff.OnPurchasing()");
    }
 
    protected override void OnPurchased() {
        Console.WriteLine("Staff.OnPurchasing()");
    }
 
}

普通员工类Staff。

public class Leader : Employee {

    private Staff _staff = null;

    public Leader() {
        _staff = new Staff();
    }

    public override void Purchase(string goods) {
        _staff.Purchase(goods);
    }

}

领导类Leader,内部维持一个员工的引用,并在Purchase采购方法调用普通员工的采购方法。完成了一次代理购物。

public class Program {

    private static Employee _employee = null;

    public static void Main(string[] args) {
        _employee = new Leader();
        _employee.Purchase("desk");

        Console.ReadKey();
    }

}

以上是调用方的代码,以下是这个案例的输出结果:

Staff.OnPurchasing()
Purchase some desks!
Staff.OnPurchasing()

🚀总结

🔎1.优点

代理模式(Proxy Pattern)具有许多优点,这些优点使得它成为软件设计中常用的模式之一:

  1. 控制访问:代理模式允许你控制对对象的访问,这可以用于实现权限控制、安全性检查和访问限制。

  2. 延迟加载:代理模式可以实现延迟加载(Lazy Loading),只有在需要时才创建和初始化真实对象。这有助于提高性能和节省资源。

  3. 实现虚拟代理:虚拟代理是一种特殊类型的代理,它可以用于管理大量对象中的某些复杂或昂贵的对象。虚拟代理在需要时才加载真实对象,从而减少初始化成本。

  4. 实现远程代理:代理模式可以用于实现远程代理,允许客户端通过代理对象访问位于远程服务器上的真实对象,从而支持分布式系统开发。

  5. 实现缓存:代理模式可以用于实现缓存,代理对象可以维护已经访问过的真实对象的副本,以便在需要时返回缓存的对象,提高性能。

  6. 记录日志:代理模式可以用于记录日志或跟踪客户端对真实对象的请求,这对于调试和监控应用程序非常有帮助。

  7. 实现智能引用:代理模式可以用于实现智能引用,智能引用代理可以记录对真实对象的引用次数,以便在不再被引用时释放资源。

  8. 解耦客户端和真实对象:代理模式将客户端与真实对象解耦,客户端不需要直接访问真实对象,这提高了代码的灵活性和可维护性。

  9. 透明性:在某些情况下,代理模式可以提供透明性,客户端不需要知道它正在使用代理而不是真实对象。

代理模式是一种非常有用的设计模式,它可以应用于各种场景,帮助解决访问控制、性能优化、资源管理和分布式系统等问题,同时提高了代码的可维护性和可扩展性。

🔎2.缺点

尽管代理模式(Proxy Pattern)具有许多优点,但也存在一些缺点和限制,需要在使用时考虑和权衡:

  1. 增加复杂性:引入代理会增加系统的复杂性,因为需要额外的代理类来封装真实对象,可能需要多层代理。这会增加代码量和理解成本。

  2. 对性能有影响:在一些情况下,代理模式可能会引入性能损耗,特别是在频繁创建和销毁代理对象时。延迟加载和虚拟代理可能会导致响应时间变长。

  3. 可能引起循环引用:如果代理对象持有对真实对象的引用,而真实对象也可以访问代理对象,可能会导致循环引用的问题,需要特别注意管理。

  4. 不适用于复杂场景:在一些复杂的场景中,代理模式可能不适用或不够灵活,例如涉及多个真实对象交互的情况。

  5. 需要确保一致性:代理模式需要确保代理类的行为与真实对象的行为保持一致,这可能需要花费额外的精力来维护和同步。

  6. 可能导致单一责任原则问题:如果代理对象承担了太多职责,可能违反了单一责任原则,导致代码设计不佳。

  7. 难以理解和调试:过多的代理层可能会使程序更难理解和调试,尤其是在复杂的代理嵌套场景中。

  8. 可能需要额外的内存:虚拟代理和远程代理可能需要在内存中维护缓存或连接等,这可能会占用额外的内存。

代理模式是一种强大的设计模式,但在使用时需要权衡其优点和缺点,根据具体场景选择是否使用以及如何使用。避免过度使用代理模式,特别是在简单场景下,以避免引入不必要的复杂性和性能问题。

🔎3.使用场景

代理模式(Proxy Pattern)适用于许多不同的场景,其中一些常见的使用场景包括:

  1. 延迟加载:当需要延迟加载对象时,可以使用代理模式。例如,加载大型图像或复杂对象,只有在实际需要显示或使用时才加载,以提高性能。

  2. 权限控制:代理模式可以用于实现权限控制,确保只有具有特定权限的用户或客户端可以访问某些对象或功能。这对于应用程序中的安全性非常重要。

  3. 虚拟代理:虚拟代理用于管理大量对象中的某些复杂或昂贵的对象。例如,在绘制大型图形界面中,只有在需要显示具体组件时才创建和初始化它们。

  4. 远程代理:远程代理用于在分布式系统中访问远程服务器上的对象。客户端通过代理对象与远程对象通信,以便执行远程操作。

  5. 缓存:代理模式可以用于实现缓存,代理对象可以维护已经访问过的真实对象的副本,以便在需要时返回缓存的对象,提高性能。

  6. 日志记录:代理模式可以用于记录日志或跟踪客户端对真实对象的请求,以便进行调试和监控。

  7. 智能引用:代理模式可以用于实现智能引用,跟踪对真实对象的引用次数,并在不再被引用时释放资源。

  8. 代理池:在需要管理多个连接或资源时,可以使用代理模式创建代理池,以确保资源的有效使用和回收。

  9. 监控和统计:代理模式可用于监控对象的使用情况,例如统计某个对象被访问的次数或时间,以便进行性能分析。

代理模式在需要控制、管理、延迟加载、保护或优化对对象的访问时非常有用。它提供了一种灵活的方式来封装和管理对象的访问,同时保持客户端与真实对象之间的松耦合关系。在设计软件时,根据具体需求和场景考虑是否使用代理模式。


🚀感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。

在这里插入图片描述

再次感谢您的阅读和支持!

最诚挚的问候, “愚公搬代码”

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。