设计模式实战:透彻解析代理模式
模式定义
代理模式(Proxy Pattern)是一种结构型设计模式,通过代理对象控制对原始对象的访问。代理在客户端和目标对象之间充当中介,可增强目标对象的功能或控制访问权限。
核心思想
访问控制:代理对象作为守门人控制对真实对象的访问
功能增强:在不修改原对象的基础上添加额外功能
延迟加载:推迟高开销对象的初始化到真正需要时
适用场景
远程服务代理(如RPC调用)
虚拟代理(延迟加载大资源)
保护代理(权限控制)
智能引用(对象访问统计)
缓存代理(请求结果缓存)
模式结构
Subject:定义真实对象和代理的公共接口
RealSubject:真实业务对象
Proxy:代理对象,持有真实对象引用
PHP实现示例:图片加载代理
<?php
// 图片接口
interface Image {
public function display();
}
// 真实图片类
class RealImage implements Image {
private $filename;
public function __construct(string $filename) {
$this->filename = $filename;
$this->loadFromDisk();
}
private function loadFromDisk() {
echo "加载大尺寸图片: {$this->filename}\n";
}
public function display() {
echo "显示图片: {$this->filename}\n";
}
}
// 图片代理类
class ProxyImage implements Image {
private $realImage;
private $filename;
public function __construct(string $filename) {
$this->filename = $filename;
}
public function display() {
if (!$this->realImage) {
$this->realImage = new RealImage($this->filename);
}
$this->realImage->display();
}
}
// 客户端使用
$image1 = new ProxyImage("photo1.jpg");
$image2 = new ProxyImage("photo2.jpg");
// 图片仅在首次显示时加载
$image1->display(); // 真实加载
$image1->display(); // 直接显示
$image2->display(); // 真实加载
Go实现示例:API访问保护代理
package main
import "fmt"
// 服务接口
type Server interface {
HandleRequest(url string) (int, string)
}
// 真实服务
type RealServer struct{}
func (s *RealServer) HandleRequest(url string) (int, string) {
return 200, fmt.Sprintf("处理成功: %s", url)
}
// 保护代理
type AuthProxy struct {
server Server
authToken string
}
func NewAuthProxy(token string) *AuthProxy {
return &AuthProxy{
server: &RealServer{},
authToken: token,
}
}
func (p *AuthProxy) HandleRequest(url string) (int, string) {
if p.authToken != "secret" {
return 403, "未授权访问"
}
return p.server.HandleRequest(url)
}
func main() {
// 创建未授权的代理
proxy1 := NewAuthProxy("guest")
code, resp := proxy1.HandleRequest("/api/data")
fmt.Printf("%d: %s\n", code, resp) // 403
// 创建有效代理
proxy2 := NewAuthProxy("secret")
code, resp = proxy2.HandleRequest("/api/data")
fmt.Printf("%d: %s\n", code, resp) // 200
}
模式优缺点
优点:
职责清晰,符合单一职责原则
扩展性强,无需修改原对象
控制对象生命周期
支持分布式和复杂对象管理
缺点:
可能引入额外性能开销
增加系统复杂度
请求响应可能延迟(代理处理时间)
不同语言实现差异
代理模式变种
虚拟代理:延迟创建开销大的对象(如PHP示例)
保护代理:控制访问权限(如Go示例)
远程代理:处理远程服务调用
缓存代理:存储请求结果
智能引用代理:添加对象生命周期管理
总结
代理模式通过引入代理层,实现了对原始对象的访问控制和功能增强。在需要添加间接层进行访问控制、延迟加载或功能扩展的场景下,该模式能有效解耦客户端与真实对象。不同语言在实现方式上各有特点:PHP更倾向于使用接口和类继承,而Go则通过结构体组合实现更灵活的代理机制。
实际开发中需要注意:
明确代理的职责边界
避免过度使用导致层级过深
关注代理带来的性能影响
区分代理模式与装饰器模式(关注点不同)
掌握代理模式的核心在于理解"间接访问"的思想,根据具体需求选择合适的代理类型,构建灵活可控的对象访问体系。
License:
CC BY 4.0