【五】Python 代理模式

news2024/11/15 5:31:57

文章目录

  • 5.1 代理模式概述
    • 5.1.1 代理介绍
    • 5.1.2 代理模式的作用
  • 5.2 代理模式的UML类图
  • 5.3 了解不同类型的代理
    • 5.3.1虚拟代理
    • 5.3.2 远程代理
    • 5.3.3 保护代理
    • 5.3.4 智能代理
  • 5.4 现实世界中的代理模式
    • 5.5 代理模式的优点
    • 5.6 门面模式和代理模式之间的比较

5.1 代理模式概述

5.1.1 代理介绍

代理通常就是一个介于请求方和提供方之间的中介系统。
在设计模式的上下文中,代理是充当实际对象接口的类。对象类型可以是多样化的,例如网络连接、内存和文件中的大对象,等等。简而言之,代理就是封装实际服务对象的包装器或代理人。代理可以为其包装的对象提供附加功能,而无需更改对象的代码。

5.1.2 代理模式的作用

代理模式的主要目的是为其他对象提供一个代理者或占位符,从而控制对实际对象的访问。
概括来说可以归纳为以下几个方面:

  • 它能够以更简单的方式表示一个复杂的系统。例如,涉及多个复杂计算或过程的系统应该提供一个更简单的接口,让它充当客户端的代理。
  • 它提高了现有的实际对象的安全性。在许多情况下,都不允许客户端直接访问实际对象。这是因为实际对象可能受到恶意活动的危害。这时候,代理就能起到抵御恶意活动的盾牌作用,从而保护了实际的对象。
  • 它为不同服务器上的远程对象提供本地接口。一个明显的例子是客户端希望在远程系统上运行某些命令的分布式系统,但客户端可能没有直接的权限来实现这一点。因此它将请求转交给本地对象(代理),然后由远程机器上的代理执行该请求。
  • 它为消耗大量内存的对象提供了一个轻量级的句柄。有时,你可能不想加载主要对象,除非它们真的有必要。这是因为实际对象真的很笨重,可能需要消耗大量资源。一个典型的例子是网站用户的个人简介头像。你最好在列表视图中显示简介头像的缩略图,当然,为了展示用户简介的详细介绍,你就需要加载实际图片了。

让我们通过一个简单的例子来理解该模式。
其中Actor 是被代理的对象。代理对象Agent 用于查看Actor是否正处于忙碌状态。如果Actor 正忙,则调用Actor().occupied()方法;如果Actor不忙,则返回Actor().available()方法。

class Actor(object):
    def __init__(self):
        self.isBusy = False
    def occupied(self):
        self.isBusy = True
        print(type(self).__name__, "Actor被占用")

    def available(self):
        self.isBusy = False=
        print(type(self).__name__, "Actor空闲")
    def getStatus(self):
        return self.isBusy
class Agent(object):
    def __init__(self):
        self.principal = None
    def work(self):
        self.actor = Actor()
        if self.actor.getStatus():
            self.actor.occupied()
        else:
            self.actor.available()
if __name__ == '__main__':
    r = Agent()
    r.work()

代理设计模式主要完成了以下工作。

  • 它为其他对象提供了一个代理,从而实现了对原始对象的访问控制。
  • 它可以用作一个层或接口,以支持分布式访问。
  • 它通过增加代理,保护真正的组件不受意外的影响。

5.2 代理模式的UML类图

现在,我们可以借助于图5-1中的UML图来探讨代理模式。正如我们在上一段中所介
绍的那样,代理模式有3个主要角色:制作公司、经纪人和演员。下面,让我们把这些角
色放入一个UML图中,看看这些类如何关联:

在这里插入图片描述

通过观察这个UML图,你会发现这个模式有下述3个主要的参与者。
代理:它维护一个引用,允许代理(Proxy)通过这个引用来访问实际对象。它提供了一个与主题 (Subject)相同的接口,以便代理可以替换真实的主题。代理还负责创建和删除真实主题(RealSubject)。
主题:它定义了RealSubject 和Proxy的公共接口。以Proxy和RealSubject的形式实现主题(Subject),使用 RealSubject 的任何地方都可以使用代理(Proxy)。
真实主题:它定义代理(Proxy)所代表的真实对象
从数据结构的角度来看,UML图可以表示如下。

  • 代理:它是一个控制对 RealSubject 类访问的类。它处理客户端的请求,负责创建或删除 RealSubject。

  • 主题/真实主题:主题是定义真实主题(RealSubject)和代理(Proxy)相类似的接口。RealSubject 是 Subject 接口的实际实现。它提供了真正的功能,然后由客户端使用。

  • 客户端:它访问要完成工作的 Proxy类。Proxy类在内部控制对 RealSubject的访问,并引导客户端(client)所请求的工作。

5.3 了解不同类型的代理

在许多常见的情形中,都会用到代理。在本章开头部分,我们已经对部分情形进行了讨论。根据代理的使用方式,我们可以将它们分为虚拟代理、远程代理、保护代理和智能

代理。在本小节中,我们将会进行更加深入的探讨。

5.3.1虚拟代理

在这里,你将详细了解虚拟代理。如果一个对象实例化后会占用大量内存的话,可以先利用占位符来表示,这就是所谓的虚拟代理。例如,假设你想在网站上加载大型图片而这个请求需要很长时间才能加载完成。通常,开发人员将在网页上创建一个占位符图标以提示这里有图像。但是,只有当用户实际点击图标时才会加载图像,从而节省了向存储器中加载大型图像的开销。因此,在虚拟代理中,当客户端请求或访问对象时,才会创建实际对象。

5.3.2 远程代理

远程代理可表述如下:它给位于远程服务器或不同地址空间上的实际对象提供了一个本地表示。例如,你希望为应用程序建立一个监控系统,而该应用涉及多个 Web 服务器数据库服务器、芹菜 (celery) 任务服务器、缓存服务器,等等。如果我们要监视这些服务器的CPU 和磁盘利用率,就需要建立一个对象,该对象能够用于监视应用程序运行的上下文中,同时还可以执行远程命令以获取实际的参数值。在这种情况下,建立一个作为远程对象的本地表示的远程代理对象将可以帮助我们实现这个目标。

5.3.3 保护代理

你可以通过以下几点加深对保护代理的理解。这种代理能够控制 Realsubject 的敏感对象的访问。例如,在当今分布式系统的世界中,Web 应用会提供多个服务,这些服务相互协作来提供各种功能。现在,在这样的系统中,认证服务充当负责认证和授权的保护性代理服务器。在这种情况下,代理自然有助于保护网站的核心功能,防止无法识别或未授权的代理访问它们。因此,代理对象会检查调用者是否具有转发请求所需的访问权限。

5.3.4 智能代理

智能代理在访问对象时插入其他操作。例如,假设在系统中有一个核心组件,它将状态信息集中保存在一个地点。通常情况下,这样的组件需要被多个不同的服务调用以完成它们的任务,并且可能导致共享资源的问题。与让服务直接调用核心组件不同,智能代理是内置的,并且会在访问之前检查实际对象是否被锁定,以确保没有其他对象可以更改它

5.4 现实世界中的代理模式

我们将通过付款用例来展示代理模式的现实应用场景。让我们假设,你在商场溜达,看中了一件漂亮的牛仔衫。你想买这件衬衫,但手里的现金却不够了。
这要是在不久以前,你可以去 ATM 取钱,然后来到商场付款。在更早的时候,通常使用的是银行支票,这样你就必须去银行提款,然后再回商场付款。
得益于银行业务的发展,后来出现了一种称为借记卡的东西。所以现在,你买东西的时候,只要在商家刷一下借记卡,这笔钱就会划入商家的账户,从而完成支付。
下面,我们利用 Python v3.5来开发一个应用程序,实现上述示例。首先从客户端开始:你去了商场,现在想买一件漂亮的牛仔衫。让我们看看如何编写客户端代码。

  • 你的行为由类You(即客户端)来表示。
  • 为了购买衬衫,该类提供了make payment()方法
  • 特殊方法_init()会调用代理并将其实例化。
  • makepayment()方法在内部调用代理的方法进行付款。
  • 如果付款成功,将返回 del()方法。
class You:
    def __init__(self):
        print("You::Lets buy the Denim shirt")
        self.debitCard= DebitCard()
        self.isPurchased = None
    def make_payment(self):
        self.isPurchased = self.debitCard.do_pay()
    def __del__(self):
        if self.isPurchased:
            print("You::Wow! Denim shirt is Mine :-)")
        else:
            print("You::I should earn more :(")
you=You()
you.make_payment()

现在让我们讨论一下主题。我们知道,主题是由代理和真实主题实现的接口。

  • 在这个例子中,主题是Payment类。它是一个抽象基类,代表一个接口。
  • 付款具有一个do_pay()方法,该方法需要借助代理和真实主题来实现。
    下面我们通过具体的代码来考察这些方法:
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
	@abstractmethod
	def do_pay(self):
		pass

在这个场景中,我们还开发了代表真实主题的Bank类:

  • Bank实际完成从你的账户向商家账户划账的工作。
  • Bank 提供了多个方法来处理付款。代理使用setCard()方法将借记卡详细信息
    发送给银行。
  • __getAccount()方法是Bank的私有方法,用于获取借记卡持有人的账户详细
    信息。为了简单起见,我们强制使用与账号相同的借记卡号。
  • Bank 还有__hasFunds()方法,它用来查看账户持有人在账户中是否有足够的资
    金来为衬衫付款。
  • 由Bank类(通过Payment接口)实现的do_pay()方法实际上负责根据可用资金
    向商家付款:
class Bank(Payment):
	def __init__(self):
		self.card = None
		self.account= None
	def __getAccount(self):
		self.account = self.card # Assume card number is account number
		return self.account
	def __hasFunds(self):
		print("Bank:: Checking if Account", self. __getAccount(),
		"has enough funds")
		return True
	def setCard(self, card):
		self.card = card
	def do_pay (self):
		if self.__hasFunds():
			print("Bank:: Paying the merchant")
			return True
		else:
			print("Bank:: Sorry, not enough funds!")
			return False

让我们现在来理解最后一部分,即与代理有关的部分。

  • DebitCard类是此处的代理。当你想要付款时,它会调用do_pay()方法。这是
  • 因为你不想跑去银行提款,然后再跑回商家完成支付。
  • DebitCard类充当真实主题(银行)的代理。
  • payWithCard()方法在内部控制真实主题(Bank类)对象的创建,并向银行提
    供借记卡的详细信息。
  • Bank在内部对账户进行检查并完成支付,具体如代码段所述:
class DebitCard(Payment):
	def __init__(self):
		self.bank = Bank()
	def do_pay(self):
		card = input("Proxy:: Punch in Card Number: ")
		self.bank.setCard(card)
		return self.bank.do_pay()

5.5 代理模式的优点

前面,我们已经学习了代理模式在现实世界中的工作原理,接下来让我们了解一下代
理模式的优点。

  • 代理可以通过缓存笨重的对象或频繁访问的对象来提高应用程序的性能。
  • 代理还提供对于真实主题的访问授权。因此,只有提供合适权限的情况下,这个模
    式才会接受委派。
  • 远程代理还便于与可用作网络连接和数据库连接的远程服务器进行交互,并可用于
    监视系统。

5.6 门面模式和代理模式之间的比较

门面模式和代理模式都是结构型设计模式。它们的相似之处在于,都是在真实对象的
前面加入一个代理/门面对象。但是在意图或目的方面,这两种模式的确存在差异,具体如
表5-1所示。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1310640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用XAMPP在Windows系统构建一个本地Web服务器

用XAMPP在Windows系统构建一个本地Web服务器 Build a Local Web Server for Windows with XAMPP By JacksonML 本文简要介绍如何获取和安装XAMPP以实现Windows环境下本地Web服务器的过程,希望对广大网友和学生有所帮助。 所谓本地Web服务器,即使用本地…

Python框架篇(5):FastApi-中间件使用

1.介绍 1.1 官网介绍 "中间件"是一个函数,它在每个请求被特定的路径操作处理之前,以及在每个响应返回之前工作. 它接收你的应用程序的每一个 请求. 然后它可以对这个 请求做一些事情或者执行任何需要的代码. 然后它将 请求传递给应用程序的其他部分 (通过某种 路径操…

slurm 23.11.0集群 debian 11.5 安装

slurm 23.11.0集群 debian 11.5 安装 用途 Slurm(Simple Linux Utility for Resource Management, http://slurm.schedmd.com/ )是开源的、具有容错性和高度可扩展的Linux集群超级计算系统资源管理和作业调度系统。超级计算系统可利用Slurm对资源和作业进行管理&a…

变电站蓄电池在线监测系统(论文+源码)

1. 系统设计 本次课题为变电站蓄电池在线监测系统的设计,其系统架构如图3.1所示,包括了主控制器STC89C52单片机,液晶显示器LCD1602,模数转换器ADC0832,电流传感器ACS712,分压电阻,蜂鸣器以及温度传感器。在…

Amazon SageMaker: 拓展机器学习边界,塑造未来创新趋势

授权说明:本篇文章授权活动官方亚马逊云科技文章转发、改写权,包括不限于在 亚马逊云科技开发者社区, 知乎,自媒体平台,第三方开发者媒体等亚马逊云科技官方渠道。 近期在 re:Invent 2023 大会上,亚马逊云科技发布了一…

如何将Galaxybase图数据库应用于电力设备管理

导读 近日,受强冷空气影响,部分北方地区出现不同程度的降雪,并持续降温。据国家电网发布的预警通知,要求启动预警响应和应急机制,密切跟踪灾害预警信息和应急响应情况,滚动研判分析覆冰、积雪、低温等对电…

vite+vue3+electron搭建项目

编辑器使用vscode,打开一个空文件夹 第一步 初始化vite项目 初始化vite项目,命令 npm init vite 第二步 下载依赖 进入新建的项目,下载依赖,命令 cd vite-projec npm i第三步 使用cnpm下载 electron依赖 新建一个终端&#…

雪花算法详细讲解

学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您: 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持,想组团高效学习… 想写博客但无从下手,急需…

HNCTF

[Week1]Interesting_http 题目提示:Give me your want! POST方式传参want参数,先随便传want1; 题目问你想要什么,肯定是flag呗,传参wantflag;提示不是admin 将数据包中的Cookie:usernotadmin修…

C# 实现图片的压缩和改变大小png、jpg和gif

环境 .net6 Magick.NET-Q16-AnyCPU 13.5 Magick.NET源码 代码 using ImageMagick;namespace ImageCompress {internal class Program{static void Main(string[] args){string inputPath "imgloading.gif"; // 输入的GIF文件路径 string outputPath "im…

ChatGPT Plus重新开启订阅

12月14日凌晨,OpenAI首席执行官Sam Altman在社交平台宣布,终于找到了更多的GPU算力,重新开启订阅ChatGPT Plus。 上个月15日,OpenAI就因为算力不足,以及用户激增等原因暂停了ChatGPT Plus订阅。 Sam表示,在…

nginx的location与rewrite

目录 一.location 二.rewrite rewrite跳转实现: 语法格式:rewrite [flag]; flag标记说明: 三.基于域名跳转 四.基于ip跳转 五.基于旧域名跳转到新域名后面加目录 六.基于参数匹配的跳转 可以同过全局变量来匹配: 基于目…

智能分析/可视化安防监控系统EasyCVR风光互补远程视频监控方案

一、背景需求 在一些偏远地区,也具有视频监控的需求。但是这类场景中,一般无法就近获取市电,如果要长距离拉取市电,建设的成本非常高且长距离传输有安全隐患,因此风光互补远程视频监控方案的需求也较多。利用风光电转…

【数组Array】力扣-303 区域和检索 - 数组不可变

目录 题目描述 解题过程 labuladong题解 题目描述 给定一个整数数组 nums&#xff0c;处理以下类型的多个查询: 计算索引 left 和 right &#xff08;包含 left 和 right&#xff09;之间的 nums 元素的 和 &#xff0c;其中 left < right 实现 NumArray 类&#xff…

【送书活动五期】Go语言开发规范指南

今天和一个小伙伴偶尔聊了两句&#xff0c;聊到现在工作的开发语言&#xff0c;大学时接触的第一个语言应该是html&#xff0c;系统且简单的学习了前端语言&#xff0c;之后伴随着学校的课程&#xff0c;C、C#、Java都有涉及&#xff0c;然后就一直已Java为主了&#xff0c;也是…

工厂如何制定OEE目标

设备综合效率OEE&#xff08;Overall Equipment Effectiveness&#xff09;是衡量工厂生产设备利用率和效率的重要指标。制定合适的OEE目标对于工厂的生产效率和效益至关重要。制定OEE目标需要综合考虑工厂的生产能力、设备状态、生产计划和质量要求等因素。下面将介绍一般工厂…

【Spring】01 Bean 介绍

文章目录 1. 定义2. 特性1&#xff09;可重用性2&#xff09;可配置性3&#xff09;可管理性 3. 生命周期1&#xff09;实例化2&#xff09;属性设置3&#xff09;初始化4&#xff09;使用5&#xff09;销毁 4. 配置方式1&#xff09;XML配置2&#xff09;注解配置3&#xff09…

3DMax物理画笔物体填充放置绘制画笔插件安装使用方法

3DMax物理画笔物体填充放置绘制画笔插件&#xff0c;允许您使用笔刷以非常自然的方式用物品快速填充场景&#xff0c;并使用刚体模拟自动放置它们。 无论你是从事建筑、游戏电影还是商业。。。等等&#xff0c;你经常需要用一些物品为你的场景添加细节。手工放置它们是乏味的&…

大数据技术10:Flink从入门到精通

导语&#xff1a;前期入门Flink时&#xff0c;可以直接编写通过idea编写Flink程序&#xff0c;然后直接运行main方法&#xff0c;无需搭建环境。我碰到许多初次接触Flink的同学&#xff0c;被各种环境搭建、提交作业、复杂概念给劝退了。前期最好的入门方式就是直接上手写代码&…

【ET8框架入门】2.ET框架解析

菜单栏相关&#xff1a;ENABLE_DLL选项 ET->ChangeDefine->ADD_ENABLE_DLL/REMOVE_ENABLE_DLL 一般在开发阶段使用Editor时需要关闭ENABLE_DLL选项。该选项关闭时&#xff0c;修改脚本之后&#xff0c;会直接重新编译所有的代码&#xff0c;Editor在运行时会直接使用最…