结构型——代理模式

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

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

特点

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

模式结构

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

维度 代理模式 外观模式 装饰器模式 适配器模式
核心目的 控制对象访问 简化复杂系统接口 动态扩展对象功能 接口兼容性转换
结构特点 代理与真实对象实现相同接口 外观类聚合多个子系统接口 装饰器模式聚合被装饰对象 适配器模式聚合被适配对象
对象关系 代理对象持有真实对象 外观持有多个子系统对象 装饰器包裹原始对象 适配器持有或继承被适配对象
接口一致性 保持与真实对象接口一致 提供新的简化接口 保持与原始对象接口一致 转换接口以匹配目标需求
扩展方向 访问控制逻辑 接口简化与整合 功能叠加 接口适配
相关推荐
A__tao4 小时前
Elasticsearch Mapping 一键生成 Java 实体类(支持嵌套 + 自动过滤注释)
java·python·elasticsearch
研究点啥好呢4 小时前
Github热门项目推荐 | 创建你的像素风格!
c++·python·node.js·github·开源软件
迷藏4944 小时前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源
明日清晨5 小时前
python扫码登录dy
开发语言·python
bazhange5 小时前
python如何像matlab一样使用向量化替代for循环
开发语言·python·matlab
人工干智能5 小时前
科普:python中你写的模块找不到了——`ModuleNotFoundError`
服务器·python
unicrom_深圳市由你创科技5 小时前
做虚拟示波器这种实时波形显示的上位机,用什么语言?
c++·python·c#
小敬爱吃饭5 小时前
Ragflow Docker部署及问题解决方案(界面为Welcome to nginx,ragflow上传文件失败,Docker中的ragflow-cpu-1一直重启)
人工智能·python·nginx·docker·语言模型·容器·数据挖掘
宸津-代码粉碎机5 小时前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python
知行合一。。。6 小时前
Python--04--数据容器(集合)
python