结构型——代理模式

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

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

特点

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

模式结构

角色 描述
抽象主题 (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 适配器模式

维度 代理模式 外观模式 装饰器模式 适配器模式
核心目的 控制对象访问 简化复杂系统接口 动态扩展对象功能 接口兼容性转换
结构特点 代理与真实对象实现相同接口 外观类聚合多个子系统接口 装饰器模式聚合被装饰对象 适配器模式聚合被适配对象
对象关系 代理对象持有真实对象 外观持有多个子系统对象 装饰器包裹原始对象 适配器持有或继承被适配对象
接口一致性 保持与真实对象接口一致 提供新的简化接口 保持与原始对象接口一致 转换接口以匹配目标需求
扩展方向 访问控制逻辑 接口简化与整合 功能叠加 接口适配
相关推荐
就是一只白25 分钟前
复制地理信息python版本
python
看浪的路人34 分钟前
第1讲:Agent 到底是什么?和 Chatbot 有什么区别
python·ai
瓦学妹1 小时前
什么是网络索引?它是如何工作的?
大数据·网络·python·网络爬虫
天天爱吃肉82182 小时前
商用车多体动力学实战笔记|第6篇:动力传动系统(发动机、变速箱、分动器、TCS、LSD限滑差速)
大数据·人工智能·笔记·python·嵌入式硬件·汽车
海盗12342 小时前
微软技术周报 ——2026-08-03
后端·python·microsoft·c#·.netcore
大数据魔法师2 小时前
【最全详解】DuckDB Python 全套 API 语法、参数与实战用法(零基础全覆盖)
python·数据分析
MC皮蛋侠客3 小时前
SQLAlchemy 系列(七):高级建模与高效写入——批量 DML、方言与扩展
数据库·python
Zane19944 小时前
@property 到底是怎么把方法伪装成属性的?一文吃透 property、staticmethod、classmethod
后端·python
qq_316411034 小时前
AI 情感陪伴智能潮玩软硬件一体化开发案例
人工智能·python
废弃的小码农4 小时前
功能测试--Day07--Python编程基础
开发语言·python