Proxy
代理模式通过提供对象的替代品或其占位符控制访问对象,在给对象提交请求前后执行处理操作
是否使用代理模式关注以下问题
安全性:控制资源访问权限,如数据库
延迟加载:管理高时间成本(复杂程序)或高空间成本(加载大文件)操作,待需要时调用
功能扩展:在代理中加入日志、统计、监控等功能,无需修改原始对象
缺点
代码冗余,复杂性增加,降低可读性和维护性
频繁调用时影响性能,特别是动态代理的反射调用
应用场景
描述
虚拟代理
通过代理对象延迟加载,按需访问资源,提升响应速度
缓存代理
使用代理对象保存结果,避免重复计算,提高访问效率
保护代理
使用代理对象控制权限,防止非法访问对象
智能引用
使用代理对象记录对象使用信息,实现智能资源管理
远程代理
使本地对象操控远程服务,隐藏网络通信细节
CPP
静态代理:特定对象的代理需求,代理逻辑相对固定,且代理类和目标类的关系比较明确和稳定,如简单的日志记录、安全性检查等
动态代理:在运行时为对象动态添加功能,或者需要为多个接口或类提供统一的代理逻辑,例如在 AOP(面向切面编程)中的应用,如日志记录、性能监控、事务管理等
静态代理是指代理类和目标类的关系在编译时就已经确定,代理类直接与目标类耦合,而不是在执行时动态生成
适用于需要对目标对象进行功能扩展或资源管理的场景
需要为目标类的每一个方法都提供代理逻辑,这会导致代码冗余,特别是在目标类接口较多时
基本结构
Member
Full Name
Description
抽象主题类
Subject
定义代理类和目标类必须实现的统一接口
真实主题类
Real Subject
业务逻辑实现类
代理类
Proxy
代理类持有目标类的实例,并通过接口控制对目标类的访问
UML结构图
实现步骤
定义抽象接口
1 2 3 4 5 class Subject {public : virtual void Request () = 0 ; virtual ~Subject () {} };
定义真实主题类
1 2 3 4 5 6 class RealSubject : public Subject {public : void Request () override { std::cout << "RealSubject: Handling request." << std::endl; } };
定义代理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class StaticProxy : public Subject {private : RealSubject* realSubject; public : StaticProxy () { realSubject = new RealSubject (); } ~StaticProxy () { delete realSubject; } void Request () override { std::cout << "StaticProxy: Adding pre-processing logic." << std::endl; realSubject->Request (); std::cout << "StaticProxy: Adding post-processing logic." << std::endl; } };
创建代理对象
1 2 StaticProxy* proxy = new StaticProxy (); proxy->Request ();
动态代理在执行时动态地创建代理类,从而在不修改目标对象代码的情况下对目标对象的方法进行增强
动态代理在 C++ 中通常需要手动实现,不像某些高级语言(如 Java)提供内置的动态代理机制
在实现动态代理时,需要考虑线程安全性和资源管理等问题
基本结构
与静态代理一致
UML结构图
实现步骤
定义抽象接口
1 2 3 4 5 class Calculator {public : virtual int add (int a, int b) = 0 ; virtual ~Calculator () = default ; };
定义真实主题类
1 2 3 4 5 6 class SimpleCalculator : public Calculator {public : int add (int a, int b) override { return a + b; } };
定义代理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class LoggingCalculatorProxy : public Calculator {private : Calculator* target; public : LoggingCalculatorProxy (Calculator* obj) : target (obj) {} int add (int a, int b) override { std::cout << "Calling add with parameters: " << a << " and " << b << std::endl; int result = target->add (a, b); std::cout << "Addition result: " << result << std::endl; return result; } };
创建动态代理
1 2 3 4 5 6 7 Calculator* realCalculator = new SimpleCalculator (); Calculator* proxyCalculator = new LoggingCalculatorProxy (realCalculator); int result = proxyCalculator->add (3 , 5 );delete realCalculator;delete proxyCalculator;
Fortran
以下代码只尽量确保与 CPP 形式一致,不一定是最佳实践
定义抽象接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 module subject_module implicit none type , abstract :: Subject contains procedure (request), deferred :: request end type Subject abstract interface subroutine request(this) import Subject class (Subject), intent (inout) :: this end subroutine request end interface end module subject_module
定义真实主题类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 module real_subject_module use subject_module implicit none type , extends (Subject) :: RealSubject contains procedure :: request => request_real end type RealSubject contains subroutine request_real(this) class (RealSubject), intent (inout) :: this print *, "realsubject: handling request." end subroutine request_real end module real_subject_module
定义代理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 module static_proxy_module use subject_module use real_subject_module implicit none type , extends (Subject) :: StaticProxy private class (Subject), pointer :: realsubject => null() contains procedure :: request => request_proxy final :: finalize_proxy end type StaticProxy contains subroutine request_proxy(this) class (StaticProxy), intent (inout) :: this print *, "staticproxy: adding pre-processing logic." call this%realsubject%request() print *, "staticproxy: adding post-processing logic." end subroutine request_proxy subroutine finalize_proxy(this) type (StaticProxy), intent (inout) :: this if (associated (this%realsubject)) then deallocate (this%realsubject) end if end subroutine finalize_proxy end module static_proxy_module
创建代理对象
1 2 type (StaticProxy) :: proxycall proxy%request()
Reference
refactoringguru | 代理模式
ShaderJoy | C++11 实现优雅的 AOP 框架(动态代理模式)
Joee | C++设计模式-结构型-代理模式
知乎 | 代理模式的灵活性有何优势
阿里云 | C++代理模式探索
CSDN | 代理模式深度解析