结构型——代理模式

结构型------代理模式

代理模式指的是通过创建一个代理来控制对原始对象的访问。代理在客户端与实际对象之间充当"中介"

特点

  • 访问控制:代理对象可以控制对实际对象的访问,从而实现对访问权限的控制。
  • 延迟加载:代理对象可以在实际对象被调用时才创建,从而实现延迟加载。
  • 解耦: 客户端金依赖代理接口,可以与实际对象分离,从而实现解耦。
  • 类型多样:虚拟代理(既延迟加载)、缓存代理(缓存对象)、远程代理(远程对象)、保护代理(权限控制)等。

模式结构

角色 描述
抽象主题 (Subject) 声明真实主题和代理主题的共同接口。客户端依赖此接口
真实主题 (RealSubject) 实现抽象主题定义的接口,并提供其功能实现。实际执行业务逻辑的对象
代理主题 (Proxy) 实现抽象主题定义的接口,并持有真实主题的引用。代理主题控制对真实主题的访问

代理模式类型

类型 应用场景
虚拟代理 当需要创建一个大开销的对象时,创建一个代理对象,直到需要时才创建真实的对象。 也叫延迟加载(比如在图片加载时,先加载一张占位图,当图片加载完成后再替换占位图)。
保护代理 控制权限(在客户端对真实对象进行访问前,利用代理进行权限校验等操作)。
缓存代理 缓存调用结果(为优化性能,将重复计算的值缓存起来,下次使用时直接返回缓存值)。
远程代理 本地代理远程服务(将本地的请求转发到远程的对象上)。

简单示例

1. 虚拟代理

python 复制代码
from abc import ABC, abstractmethod

# 抽象主题
class Image(ABC):
    @abstractmethod
    def display(self):
        pass

# 真实主题(大开销对象)
class RealImage(Image):
    def __init__(self, filename):
        self.filename = filename
        self.load_from_disk()

    def load_from_disk(self):
        print(f"Loading {self.filename} from disk")

    def display(self):
        print(f"Displaying {self.filename}")

# 代理主题(控制加载时机)
class ProxyImage(Image):
    def __init__(self, filename):
        self.filename = filename
        self.real_image = None      # 延迟加载

    def display(self):
        if not self.real_image:
            self.real_image = RealImage(self.filename)
        self.real_image.display()

# 客户端代码
if __name__ == "__main__":
    # 创建代理,此时不会实际加载图片
    proxy_image = ProxyImage("test_image.jpg")             # Loading test_image.jpg from disk
    # 当需要展示时,实际去加载显示
    proxy_image.display()                                  # Displaying test_image.jpg

2. 保护代理

python 复制代码
from abc import ABC, abstractmethod

# 抽象主题
class DataBase(ABC):
    @abstractmethod
    def query(self, sql):
        pass

# 真实主题(实现对数据库的查询操作)
class RealDataBase(DataBase):
    def query(self, sql):
        return f"query result: {sql}"

# 代理(对请求对象进行拦截,权限验证)
class ProxyDataBase(DataBase):

    def __init__(self, user):
        self.user = user
        self.real_db = RealDataBase()

    def query(self, sql):
        if self._check_access():
            return self.real_db.query(sql)
        else:
            return "access denied"

    def _check_access(self):
        return self.user == "admin"

# 客户端代码
if __name__ == "__main__":
    proxy_db = ProxyDataBase("admin")
    print(proxy_db.query("select * from user"))         # query result: ....
    proxy_db = ProxyDataBase("guest")
    print(proxy_db.query("select * from user"))         # access denied

3. 缓存代理

python 复制代码
from abc import ABC, abstractmethod

class Calculate(ABC):
    @abstractmethod
    def calculate(self, n): pass

class RealCalculate(Calculate):

    def calculate(self, n):
        return n * n

class ProxyCalculate(Calculate):

    def __init__(self):
        self.cache = {}
        self.real_calculate = RealCalculate()

    def calculate(self, n):
        if n not in self.cache:
            self.cache[n] = self.real_calculate.calculate(n)
        return self.cache[n]

if __name__ == '__main__':
    proxy_calculate = ProxyCalculate()
    for i in range(10):
        print(proxy_calculate.calculate(i))         # 第一次计算,缓存
    for i in range(10):
        print(proxy_calculate.calculate(i))         # 第二次计算,直接从缓存中取

4.远程代理

python 复制代码
import requests

class BaiduService:
    def get_data(self, question): pass

class BaiduServiceProxy(BaiduService):
    def __init__(self):
        self.question = question
        self.baidu_api = "www.baidu.com"

    def get_data(self, question):
        response = requests.get(self.baidu_api, params={"question": question})
        return response.text

# 客户端代码
if __name__ == "__main__":
    # 客户端仅与代理交互,无需感知远程服务的存在
    baidu_service = BaiduServiceProxy()
    data = baidu_service.get_data("如何使用代理模式")
    

代理模式 VS 外观模式 VS 装饰器模式 VS 适配器模式

维度 代理模式 外观模式 装饰器模式 适配器模式
核心目的 控制对象访问 简化复杂系统接口 动态扩展对象功能 接口兼容性转换
结构特点 代理与真实对象实现相同接口 外观类聚合多个子系统接口 装饰器模式聚合被装饰对象 适配器模式聚合被适配对象
对象关系 代理对象持有真实对象 外观持有多个子系统对象 装饰器包裹原始对象 适配器持有或继承被适配对象
接口一致性 保持与真实对象接口一致 提供新的简化接口 保持与原始对象接口一致 转换接口以匹配目标需求
扩展方向 访问控制逻辑 接口简化与整合 功能叠加 接口适配
相关推荐
Gigavision6 小时前
基于BUAA-MIHR数据集的噪声解耦对比学习算法
人工智能·python·深度学习·算法
IPdodo_6 小时前
跨境 API 调用不稳定怎么办:出口、超时重试与链路监控的实践
网络·python·网络协议
Madison-No77 小时前
搭建项目测试环境
linux·运维·服务器·python
计算机编程-吉哥7 小时前
YOLO26 vs YOLO11 vs YOLOv8:深度学习咖啡果实成熟度分割系统【计算机毕业设计选题推荐】
人工智能·python·深度学习·yolo·django·毕业设计
大衛說8 小时前
11 · 异常处理与日志
python
auto_go8 小时前
Python 实战指南(7)——账本动不动就崩?先把“魔法字符串”和“裸报错”干掉
python
Beyond_System|系统之外8 小时前
【学编程】Python基础编程题100道(21-60)
开发语言·python·算法
根目录下的猫9 小时前
RK3588适配的轻量级AI模型推荐
人工智能·后端·python·目标检测
wno7049 小时前
Spring Security权限控制
java·python·spring
ShineWinsu10 小时前
对于Coze—AI:SDK的解析
人工智能·python·ai·sdk·项目·coze·字节跳动