Head First 代理模式读书分享第一部分:概述1.1 什么是代理模式?
定义:为其他对象提供一种代理以控制对这个对象的访问。
本质:用“同接口的替身”在调用前后加入你想要的“控制与增强”,在需要时“改变位置/时机/协议/生命周期”,且对使用者透明。
关键点:
控制访问:权限、限流、熔断、缓存、审计、路由、重试等。
透明一致:保持与真实主题相同接口,客户端无感。
位置透明:本地/远程一致调用体验。
生命周期与开销:按需创建与复用,降低成本。
1.2 代理模式的分类
远程代理(Remote Proxy)
作用:为远程对象提供本地代表,隐藏网络/协议/序列化差异,让“像本地调用”的代码在远端执行。
常见形态:.NET Remoting(历史)、WCF、REST API 客户端、gRPC Stub、前端生成的 TypeScript API 客户端、服务网关/SDK。
横切点:认证与租户透传、错误标准化、重试/熔断、跟踪ID/日志、带宽优化(压缩)。
虚拟代理(Virtual Proxy)
作用:延迟创建或替代开销大的对象(Lazy Loading/缓存/占位符),用“轻量替身”先行响应或缓存响应。
常见形态:延迟加载图片/大对象;首次加载后缓存;加载中显示骨架屏/占位对象。
保护代理(Protection Proxy)
作用:在访问前强制权限/数据域控制(行/列级数据权限、上下文隔离)。
常见形态:仓储/查询代理在入库/出库前注入权限过滤;方法级授权拦截;字段脱敏。
智能引用代理(Smart Reference)
作用:在引用真实对象时执行“附加动作”(引用计数、连接池、指标采集、日志、限流/熔断/重试、审计)。
常见形态:带统计的连接/客户端、带熔断/重试的远程调用包装器。
-(可选扩展)防火墙/反向代理(基础设施层):如 Nginx 作为“服务器端代理”,对外统一入口,对内路由/负载均衡/缓存/SSL 终止。
第二部分:Head First 设计模式中的代理模式2.1 经典例子回顾(糖果机远程监控:Remote Proxy)
核心:远程监控端通过“本地代理”像调用本地糖果机对象一样,实际请求被发送到远程糖果机。
.NET 对应简述(与 Java RMI 同构):
.NET Remoting 使用“透明代理(Transparent Proxy)”与“编组(序列化)”将本地方法调用转为网络调用,服务器端由远程对象执行,再将结果返回;性质与书中 Java 远程代理一致。
后续技术演进:.NET Remoting → WCF → REST/gRPC;本质一直是远程代理思想。
2.2 代理模式的设计原则
开闭原则(OCP): 代理在“相同接口”上扩展行为(认证/缓存/路由/监控),无需修改真实主题和客户端;新增能力=新增代理/拦截器即可。
单一职责原则(SRP): 真实主题只做业务;代理只做横切或访问控制;职责清晰、变更互不牵连。
-(常与代理相伴)
第三部分:综合示例
【客户端】 【服务端】
Component → Service → HTTP → DynamicController(代理) → AppService → CatchedWithPermissionUtilty
(Remote Proxy) (Dynamic Proxy) (Virtual Proxy)
Remote Proxy 示例
后端服务(真实主题):
public class DocumentManagementAppService : ApplicationService前端代理(代理对象):
export class DocumentManagementService {客户端使用(客户端):
export class DocumentComponent {Dynamic Proxy(后端动态控制器)
启动期:将 ApplicationService 映射为控制器动作(内存模型)
反射扫描程序集中的 IApplicationService 实现(可按名称/可见性等过滤)。
为每个服务方法解析并约定:
控制器前缀:/api/app/{service-kebab}(如 DocumentManagementAppService → /api/app/document-management)。
动作名:去掉 Async 后 kebab 化(如 GetDocumentWithStatusAsync → document-with-status)。
HTTP 动词推断:Get/Find→GET;Create→POST;Update→PUT;Delete/Remove→DELETE;其余默认 POST(均可被特性覆盖)。
为每个方法生成 ActionModel(路由/HTTP 动词/参数来源),注册为 ActionDescriptor(ApiExplorer/Swagger 自然可见)。
预编译 MethodInfo 为调用委托并缓存,减少反射热路径开销。
请求期:命中“内存控制器”的某个 Action → 模型绑定 → 解析服务实例 → 调用方法
MVC 路由命中 ActionDescriptor
Model Binding 把 Route/Query/Body 绑定到方法参数(含 DTO、CancellationToken)
解析对应 ApplicationService 实例
授权→验证→工作单元→审计→异常标准化
最终用 MethodInfo(通常缓存为已编译委托)在该服务实例上执行
Virtual Proxy /Protection Proxy 示例(缓存+权限控制)
public static ChargeBillEntity HAGetChargeBillByBillID(string billID)Smart Reference 示例(重试/熔断/指标)
// 扩展第四部分:总结4.1 代理模式的优缺点
优点
职责清晰:业务(真实主题)与横切(代理)解耦。
高扩展性:对扩展开放;增减能力靠“加减代理”。
智能化:透明加入重试/熔断/限流/租户/审计/观测。
缺点
复杂度提升:链路更长,需要完善观测性与治理。
性能折衷:多一层调用/序列化;需缓存/批量/压缩等优化。
4.2 何时使用
需要远程访问(RPC/HTTP/gRPC):隐藏位置/协议差异。
需要统一控制访问:认证、授权、限流、数据权限、审计、租户透传。
需要延迟加载与开销优化:虚拟代理 + 缓存。
需要增强能力:日志、监控、重试/熔断、路由、灰度、压缩/加密。
4.3 与相似模式关系
装饰器模式
相同:同接口、可叠加、透明替换。
差异:装饰器强调“功能增强”;代理强调“访问控制/位置/生命周期/远程编组”。
适配器模式
适配器“改变接口”以适配调用方;代理“保持接口相同”以控制访问。
外观模式
外观提供“更简化的统一接口”;代理在“相同接口”下控制访问/位置/时机/策略。
其他模式的影子
动态代理:运行时生成控制器/拦截器(动态控制器)。
适配器:把 AppService 的方法“适配”为 HTTP 动作。
装饰器:在代理中叠加横切(日志/授权/审计)。
外观:为复杂后端提供统一 HTTP 门面。