代理模式(Proxy Pattern)

简介: 代理模式(Proxy Pattern)是一种设计模式,通过一个中间对象(代理)来间接访问目标对象,以控制访问权限或添加额外功能。常见的代理类型包括远程代理、虚拟代理、保护代理和智能引用代理。代理模式常用于延迟加载、权限控制、日志记录等场景,能够提高系统的灵活性和安全性。

代理模式(Proxy Pattern)详解

定义

代理模式可以看作委托别人去办事。如果你想办一件事(比如访问一个资源、操作一个文件),但因为种种原因不能直接去做,就可以通过一个中间人来帮忙。这种中间人就是代理,既可以帮你完成任务,又可以加点“附加服务”,比如检查你的权限、记录操作日志等。


生活中的例子

  1. 公司前台
    假设你要找某位公司高管谈事情,你不能直接冲进高管办公室,而是要先经过前台。前台会判断你有没有预约,或者是否符合要求。前台就相当于代理,高管则是真实对象
  2. 明星经纪人
    你想请一位明星参加活动,不会直接联系明星,而是通过经纪人。经纪人会筛选请求、谈价格,最后安排明星工作。这里,经纪人是代理,明星是真实对象
  3. 网购快递
    当你网购时,快递公司是你的代理。你买的东西最终是由快递送到你手上,商家并不直接交货给你,而是通过快递完成的。

为什么需要代理模式?

代理模式的核心在于控制访问和扩展功能。以下是常见需求:

  1. 控制访问权限:比如你不能直接访问数据库,需要验证身份。
  2. 优化性能:有些资源初始化很慢,通过代理延迟加载可以节省性能。
  3. 增加功能:可以在代理中加入日志、统计、监控等功能。

代理模式的分类

  1. 远程代理(Remote Proxy)
    让客户端像访问本地对象一样访问远程对象。例如:RPC(远程过程调用)。
  2. 虚拟代理(Virtual Proxy)
    延迟创建耗资源的对象,按需加载。例如:图片加载器在图片未加载时显示占位符。
  3. 保护代理(Protection Proxy)
    控制对对象的访问权限。例如:文件操作时的权限检查。
  4. 智能引用代理(Smart Reference Proxy)
    在对象访问时增加额外功能,例如记录访问日志或统计引用次数。

代理模式的优点和缺点

优点

  1. 单一职责:将真实对象的核心功能与附加功能分离。
  2. 灵活性强:可以动态添加功能,如权限控制、日志记录。
  3. 资源管理:可以有效管理复杂对象的生命周期(如延迟加载)。

缺点

  1. 代码复杂性增加:引入代理后,代码结构更复杂。
  2. 性能开销:代理模式引入了额外的操作,可能会影响性能。

使用场景

序号 场景 具体案例描述 作用与目的
1 延迟加载 图片查看器延迟加载高清图片,先显示占位符。 减少初始页面加载时间,提高用户体验。
2 远程调用 分布式系统中访问远程服务时,通过代理简化调用。 降低远程服务调用的复杂性,提高代码的可维护性和可扩展性。
3 权限控制 用户权限不足时,通过代理阻止对敏感资源的直接访问。 增强系统的安全性,确保只有授权用户才能访问敏感资源。
4 监控与日志 为真实对象的每次操作记录日志,用于分析和调试。 便于追踪系统行为,分析问题原因,优化系统性能。
5 事务管理 数据库操作时,代理处理事务的提交与回滚。 确保数据库操作的原子性、一致性、隔离性和持久性(ACID属性),维护数据的完整性。

更详细的实现步骤

  1. 定义抽象接口(Subject):所有请求的公共接口。
  2. 实现真实对象(RealSubject):负责处理具体的业务逻辑。
  3. 实现代理对象(Proxy)
  • 保存一个对真实对象的引用。
  • 在真实对象的方法调用前后,添加权限检查、日志等附加功能。
  1. 客户端通过代理访问真实对象

更通俗的代码说明

C++ 示例:图片延迟加载代理

#include <iostream>
#include <string>
#include <memory>
using namespace std;

// 抽象接口
class Image {
public:
   virtual void display() = 0;
   virtual ~Image() = default;
};

// 实际图片类
class RealImage : public Image {
private:
   string fileName;

   void loadFromDisk() {
       cout << "Loading " << fileName << " from disk..." << endl;
   }

public:
   RealImage(const string& fileName) : fileName(fileName) {
       loadFromDisk();
   }

   void display() override {
       cout << "Displaying " << fileName << endl;
   }
};

// 代理图片类
class ProxyImage : public Image {
private:
   unique_ptr<RealImage> realImage;
   string fileName;

public:
   ProxyImage(const string& fileName) : fileName(fileName) {}

   void display() override {
       if (!realImage) {
           realImage = make_unique<RealImage>(fileName);
       }
       realImage->display();
   }
};

// 客户端代码
int main() {
   unique_ptr<Image> image = make_unique<ProxyImage>("test.jpg");
   cout << "Image will not load until display() is called:" << endl;
   image->display(); // 第一次调用会加载图片
   image->display(); // 后续调用直接显示,不重新加载
   return 0;
}

C# 示例:远程代理模拟

using System;

// 抽象接口
public interface IImage {
   void Display();
}

// 真实图片类
public class RealImage : IImage {
   private string FileName;

   public RealImage(string fileName) {
       FileName = fileName;
       LoadFromDisk();
   }

   private void LoadFromDisk() {
       Console.WriteLine($"Loading {FileName} from disk...");
   }

   public void Display() {
       Console.WriteLine($"Displaying {FileName}");
   }
}

// 代理图片类
public class ProxyImage : IImage {
   private RealImage _realImage;
   private string FileName;

   public ProxyImage(string fileName) {
       FileName = fileName;
   }

   public void Display() {
       if (_realImage == null) {
           _realImage = new RealImage(FileName);
       }
       _realImage.Display();
   }
}

// 客户端代码
class Program {
   static void Main(string[] args) {
       IImage image = new ProxyImage("test.jpg");
       Console.WriteLine("Image will not load until Display() is called:");
       image.Display(); // 第一次调用加载图片
       image.Display(); // 后续调用不再加载
   }
}


代理模式的类图


总结

  1. 定义核心:代理为真实对象提供了一个间接访问的方式,方便控制权限或扩展功能。
  2. 实现灵活:代码可以根据需要添加日志、延迟加载或权限控制等功能。
  3. 理解方法:通过生活例子结合实际代码,代理模式的作用更加直观。
目录
相关文章
|
6天前
|
存储 运维 安全
云上金融量化策略回测方案与最佳实践
2024年11月29日,阿里云在上海举办金融量化策略回测Workshop,汇聚多位行业专家,围绕量化投资的最佳实践、数据隐私安全、量化策略回测方案等议题进行深入探讨。活动特别设计了动手实践环节,帮助参会者亲身体验阿里云产品功能,涵盖EHPC量化回测和Argo Workflows量化回测两大主题,旨在提升量化投研效率与安全性。
云上金融量化策略回测方案与最佳实践
|
8天前
|
人工智能 自然语言处理 前端开发
从0开始打造一款APP:前端+搭建本机服务,定制暖冬卫衣先到先得
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。
8011 19
|
11天前
|
Cloud Native Apache 流计算
资料合集|Flink Forward Asia 2024 上海站
Apache Flink 年度技术盛会聚焦“回顾过去,展望未来”,涵盖流式湖仓、流批一体、Data+AI 等八大核心议题,近百家厂商参与,深入探讨前沿技术发展。小松鼠为大家整理了 FFA 2024 演讲 PPT ,可在线阅读和下载。
4357 10
资料合集|Flink Forward Asia 2024 上海站
|
19天前
|
人工智能 自动驾驶 大数据
预告 | 阿里云邀您参加2024中国生成式AI大会上海站,马上报名
大会以“智能跃进 创造无限”为主题,设置主会场峰会、分会场研讨会及展览区,聚焦大模型、AI Infra等热点议题。阿里云智算集群产品解决方案负责人丛培岩将出席并发表《高性能智算集群设计思考与实践》主题演讲。观众报名现已开放。
|
12天前
|
自然语言处理 数据可视化 API
Qwen系列模型+GraphRAG/LightRAG/Kotaemon从0开始构建中医方剂大模型知识图谱问答
本文详细记录了作者在短时间内尝试构建中医药知识图谱的过程,涵盖了GraphRAG、LightRAG和Kotaemon三种图RAG架构的对比与应用。通过实际操作,作者不仅展示了如何利用这些工具构建知识图谱,还指出了每种工具的优势和局限性。尽管初步构建的知识图谱在数据处理、实体识别和关系抽取等方面存在不足,但为后续的优化和改进提供了宝贵的经验和方向。此外,文章强调了知识图谱构建不仅仅是技术问题,还需要深入整合领域知识和满足用户需求,体现了跨学科合作的重要性。
|
7天前
|
人工智能 容器
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
本文介绍了如何利用千问开发一款情侣刮刮乐小游戏,通过三步简单指令实现从单个功能到整体框架,再到多端优化的过程,旨在为生活增添乐趣,促进情感交流。在线体验地址已提供,鼓励读者动手尝试,探索编程与AI结合的无限可能。
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
|
1月前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
104580 10
|
7天前
|
消息中间件 人工智能 运维
12月更文特别场——寻找用云高手,分享云&AI实践
我们寻找你,用云高手,欢迎分享你的真知灼见!
638 39
|
5天前
|
弹性计算 运维 监控
阿里云云服务诊断工具:合作伙伴架构师的深度洞察与优化建议
作为阿里云的合作伙伴架构师,我深入体验了其云服务诊断工具,该工具通过实时监控与历史趋势分析,自动化检查并提供详细的诊断报告,极大提升了运维效率和系统稳定性,特别在处理ECS实例资源不可用等问题时表现突出。此外,它支持预防性维护,帮助识别潜在问题,减少业务中断。尽管如此,仍建议增强诊断效能、扩大云产品覆盖范围、提供自定义诊断选项、加强教育与培训资源、集成第三方工具,以进一步提升用户体验。
626 243
|
1天前
|
弹性计算 运维 监控
云服务测评 | 基于云服务诊断全方位监管云产品
本文介绍了阿里云的云服务诊断功能,包括健康状态和诊断两大核心功能。作者通过个人账号体验了该服务,指出其在监控云资源状态和快速排查异常方面的优势,同时也提出了一些改进建议,如增加告警配置入口和扩大诊断范围等。