设计模式-代理模式

Proxy

代理模式通过提供对象的替代品或其占位符控制访问对象,在给对象提交请求前后执行处理操作

  • 是否使用代理模式关注以下问题
    • 安全性:控制资源访问权限,如数据库
    • 延迟加载:管理高时间成本(复杂程序)或高空间成本(加载大文件)操作,待需要时调用
    • 功能扩展:在代理中加入日志、统计、监控等功能,无需修改原始对象
  • 缺点
    • 代码冗余,复杂性增加,降低可读性和维护性
    • 频繁调用时影响性能,特别是动态代理的反射调用
应用场景 描述
虚拟代理 通过代理对象延迟加载,按需访问资源,提升响应速度
缓存代理 使用代理对象保存结果,避免重复计算,提高访问效率
保护代理 使用代理对象控制权限,防止非法访问对象
智能引用 使用代理对象记录对象使用信息,实现智能资源管理
远程代理 使本地对象操控远程服务,隐藏网络通信细节

CPP

  1. 静态代理:特定对象的代理需求,代理逻辑相对固定,且代理类和目标类的关系比较明确和稳定,如简单的日志记录、安全性检查等
  2. 动态代理:在运行时为对象动态添加功能,或者需要为多个接口或类提供统一的代理逻辑,例如在 AOP(面向切面编程)中的应用,如日志记录、性能监控、事务管理等
  • 静态代理是指代理类和目标类的关系在编译时就已经确定,代理类直接与目标类耦合,而不是在执行时动态生成
  • 适用于需要对目标对象进行功能扩展或资源管理的场景
  • 需要为目标类的每一个方法都提供代理逻辑,这会导致代码冗余,特别是在目标类接口较多时

基本结构

Member Full Name Description
抽象主题类 Subject 定义代理类和目标类必须实现的统一接口
真实主题类 Real Subject 业务逻辑实现类
代理类 Proxy 代理类持有目标类的实例,并通过接口控制对目标类的访问

UML结构图

实现步骤

  1. 定义抽象接口
1
2
3
4
5
class Subject {
public:
virtual void Request() = 0;
virtual ~Subject() {}
};
  1. 定义真实主题类
1
2
3
4
5
6
class RealSubject : public Subject {
public:
void Request() override {
std::cout << "RealSubject: Handling request." << std::endl;
}
};
  1. 定义代理类
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. 创建代理对象
1
2
StaticProxy* proxy = new StaticProxy();
proxy->Request();
  1. 动态代理在执行时动态地创建代理类,从而在不修改目标对象代码的情况下对目标对象的方法进行增强
  2. 动态代理在 C++ 中通常需要手动实现,不像某些高级语言(如 Java)提供内置的动态代理机制
  3. 在实现动态代理时,需要考虑线程安全性和资源管理等问题

基本结构

与静态代理一致

UML结构图

实现步骤

  1. 定义抽象接口
1
2
3
4
5
class Calculator {
public:
virtual int add(int a, int b) = 0;
virtual ~Calculator() = default;
};
  1. 定义真实主题类
1
2
3
4
5
6
class SimpleCalculator : public Calculator {
public:
int add(int a, int b) override {
return a + b;
}
};
  1. 定义代理类
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. 创建动态代理
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. 定义抽象接口
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. 定义真实主题类
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. 定义代理类
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. 创建代理对象
1
2
type(StaticProxy) :: proxy
call proxy%request()

Reference

refactoringguru | 代理模式
ShaderJoy | C++11 实现优雅的 AOP 框架(动态代理模式)
Joee | C++设计模式-结构型-代理模式
知乎 | 代理模式的灵活性有何优势
阿里云 | C++代理模式探索
CSDN | 代理模式深度解析

0%