1. 设计模式原理说明
代理模式(Proxy Pattern) 是一种结构型设计模式,允许你提供一个替身或占位符对象来控制对另一个对象的访问。代理模式的主要目的是控制对真实对象的访问,可以用来添加额外的功能(如延迟加载、权限检查等),而不改变客户端的代码。代理模式通常涉及四个角色:
- Subject(主题接口):定义了RealSubject和Proxy的共同接口,这样在任何使用RealSubject的地方都可以使用Proxy。
- RealSubject(真实主题):定义了代理对象代表的真实对象,负责执行实际的业务逻辑。
- Proxy(代理):持有对RealSubject的引用,可以通过这个引用调用RealSubject的方法。代理可以在调用前后执行额外的操作,比如权限检查、日志记录等。
- Client(客户端):通过Subject接口与RealSubject或Proxy交互。
2. UML 类图及解释
UML 类图
+-------------------+ +-----------------------+
| Subject | | RealSubject |
|-------------------| |-----------------------|
| - request(): void | | - request(): void |
+-------------------+ +-----------------------+
^ ^
| |
+------------------------+
|
|
+-----------------------------+ |
| Proxy | |
|-----------------------------| |
| - subject: Subject | |
| - request(): void | |
+-----------------------------+ |
类图解释
- Subject:定义了一个公共接口,使得RealSubject和Proxy可以互换使用。
- RealSubject:实现了Subject接口,定义了真实的业务逻辑。
- Proxy:也实现了Subject接口,持有一个指向RealSubject的引用。可以在调用RealSubject的方法之前或之后执行额外的操作,例如权限检查、日志记录等。
- Client:通过Subject接口与RealSubject或Proxy交互,无需关心具体的实现细节。
3. 代码案例及逻辑详解
Java 代码案例
// 主题接口
interface Subject {
void request();
}
// 真实主题
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
// 代理
class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
// 在调用真实主题的方法之前,可以添加额外的逻辑
checkAccess();
realSubject.request();
// 在调用真实主题的方法之后,可以添加额外的逻辑
logAccess();
}
private void checkAccess() {
System.out.println("Proxy: Checking access prior to firing a real request.");
}
private void logAccess() {
System.out.println("Proxy: Logging the time of request.");
}
}
// 客户端
public class Client {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Proxy proxy = new Proxy(realSubject);
// 客户端通过代理来访问真实主题
proxy.request();
}
}
C++ 代码案例
#include <iostream>
// 主题接口
class Subject {
public:
virtual void request() = 0;
virtual ~Subject() {}
};
// 真实主题
class RealSubject : public Subject {
public:
void request() override {
std::cout << "RealSubject: Handling request.\n";
}
};
// 代理
class Proxy : public Subject {
private:
RealSubject* realSubject;
public:
Proxy(RealSubject* realSubject) : realSubject(realSubject) {}
void request() override {
checkAccess();
realSubject->request();
logAccess();
}
private:
void checkAccess() {
std::cout << "Proxy: Checking access prior to firing a real request.\n";
}
void logAccess() {
std::cout << "Proxy: Logging the time of request.\n";
}
};
// 客户端
int main() {
RealSubject* realSubject = new RealSubject();
Proxy* proxy = new Proxy(realSubject);
// 客户端通过代理来访问真实主题
proxy->request();
delete realSubject;
delete proxy;
return 0;
}
Python 代码案例
# 主题接口
class Subject:
def request(self):
raise NotImplementedError
# 真实主题
class RealSubject(Subject):
def request(self):
print("RealSubject: Handling request.")
# 代理
class Proxy(Subject):
def __init__(self, real_subject: RealSubject):
self._real_subject = real_subject
def request(self):
# 在调用真实主题的方法之前,可以添加额外的逻辑
self._check_access()
self._real_subject.request()
# 在调用真实主题的方法之后,可以添加额外的逻辑
self._log_access()
def _check_access(self):
print("Proxy: Checking access prior to firing a real request.")
def _log_access(self):
print("Proxy: Logging the time of request.")
# 客户端
if __name__ == "__main__":
real_subject = RealSubject()
proxy = Proxy(real_subject)
# 客户端通过代理来访问真实主题
proxy.request()
Go 代码案例
package main
import (
"fmt"
)
// 主题接口
type Subject interface {
request()
}
// 真实主题
type RealSubject struct{}
func (r *RealSubject) request() {
fmt.Println("RealSubject: Handling request.")
}
// 代理
type Proxy struct {
realSubject *RealSubject
}
func (p *Proxy) request() {
// 在调用真实主题的方法之前,可以添加额外的逻辑
p.checkAccess()
p.realSubject.request()
// 在调用真实主题的方法之后,可以添加额外的逻辑
p.logAccess()
}
func (p *Proxy) checkAccess() {
fmt.Println("Proxy: Checking access prior to firing a real request.")
}
func (p *Proxy) logAccess() {
fmt.Println("Proxy: Logging the time of request.")
}
// 客户端
func main() {
realSubject := &RealSubject{}
proxy := &Proxy{realSubject: realSubject}
// 客户端通过代理来访问真实主题
proxy.request()
}
4. 总结
代理模式 是一种结构型设计模式,允许你提供一个替身或占位符对象来控制对另一个对象的访问。这种模式的主要目的是在不改变客户端代码的情况下,添加额外的功能,如延迟加载、权限检查、日志记录等。
主要优点
- 职责分离:将复杂的操作封装在代理对象中,使客户端代码更加简洁。
- 增强功能:可以在不修改原始对象的情况下,通过代理对象添加额外的功能。
- 控制访问:可以限制对真实对象的访问,例如权限检查。
- 延迟初始化:可以延迟真实对象的创建,直到真正需要时才创建,从而节省资源。
主要缺点
- 增加了系统的复杂性:引入了额外的类和对象,使得系统更加复杂。
- 可能影响性能:如果代理对象中的额外操作过于复杂,可能会影响系统的性能。
适用场景
- 当需要在访问对象时添加额外的操作,如权限检查、日志记录等。
- 当需要延迟初始化昂贵的对象,以提高系统性能。
- 当需要控制对对象的访问,例如限制访问次数或频率。
- 当需要为对象提供一个安全的访问点,例如网络服务的代理。