结构型——代理模式

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

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

特点

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

模式结构

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

维度 代理模式 外观模式 装饰器模式 适配器模式
核心目的 控制对象访问 简化复杂系统接口 动态扩展对象功能 接口兼容性转换
结构特点 代理与真实对象实现相同接口 外观类聚合多个子系统接口 装饰器模式聚合被装饰对象 适配器模式聚合被适配对象
对象关系 代理对象持有真实对象 外观持有多个子系统对象 装饰器包裹原始对象 适配器持有或继承被适配对象
接口一致性 保持与真实对象接口一致 提供新的简化接口 保持与原始对象接口一致 转换接口以匹配目标需求
扩展方向 访问控制逻辑 接口简化与整合 功能叠加 接口适配
相关推荐
日升_rs几秒前
Browser-use 详细介绍&使用文档
python·ai
测试杂货铺34 分钟前
Web自动化测试详细流程和步骤
自动化测试·软件测试·python·selenium·测试工具·职场和发展·测试用例
Ronin-Lotus36 分钟前
深度学习篇---回归&分类任务的损失函数
人工智能·python·深度学习·神经网络·分类·回归
cy41302641 分钟前
python脚本处理excel文件
python·excel
hakesashou1 小时前
python如何随机选取n个不同的数字
开发语言·python
Ronin-Lotus1 小时前
深度学习篇---PaddleOCR
人工智能·python·深度学习·paddlepaddle·paddleocr·文本识别
databook1 小时前
模型的泛化性能度量:方法、比较与实现
python·机器学习·scikit-learn
一只天蝎的晋升之路2 小时前
Python中常用的测试框架-pytest和unittest
开发语言·python·pytest
好好学习啊天天向上2 小时前
flask,示例及解释
后端·python·flask
渊渟岳2 小时前
掌握设计模式--访问者模式
设计模式