Python 设计模式(第2版) -- 第二部分(结构型模式)

Python 设计模式(第2版)

然后介绍下结构型设计模式。

下面是一些结构型设计模式的例子:

  • 适配器模式:将一个接口转换成客户希望的另外一个接口。它试图根据客户端的需求来匹配不同类的接口。
  • 桥接模式:该模式将对象的接口与其实现进行解耦,使得两者可以独立工作。
  • 装饰器模式:该模式允许在运行时或以动态方式为对象添加职责。我们可以通过接口给对象添加某些属性。

门面模式 – 与门面相适

门面在隐藏内部系统复杂性的同时,为客户端提供了一个接口,以便它们可以非常轻松地访问系统。

假设要在家中举行一场婚礼,必须预订一家酒店或场地,与餐饮人员交代酒菜、布置场景,并安排背景音乐,下面我们从门面模式的角度来看待这些事情。

  • 客户端:需要在婚礼前及时完成所有的准备工作。每一项安排都应该是顶级的,这样客人才会喜欢这些庆祝活动。
  • 门面:会务经理负责与所有相关人员进行交涉,这些人员负责处理食物、花卉装饰等。
  • 子系统:它们代表提供餐饮、酒店管理和花卉装饰等服务的系统。

EventManager 扮演了门面的角色。Hotelier 类用于预订酒店。它有一个方法,用于检查当天是否有免费的酒店(__isAvailable)。Florist 类负责花卉装饰。这个类提供了 setFlowerRequirements() 方法,用于指定要使用哪些种类的花卉来装饰婚礼。Caterer 类用于跟备办宴席者打交道,并负责安排餐饮。Caterer 提供了一个公开的 setCuisine() 法,用来指定婚宴的菜肴类型。 Musician 类用来安排婚礼的音乐,它使用 setMusicType() 方法来了解会务的音乐要求。

class EventManager(object):def __init__(self):print("Event Manager:: Let me talk to the folks\n")def arrange(self):self.hotelier = Hotelier()self.hotelier.bookHotel()self.florist = Florist()self.florist.setFlowerRequirements()self.caterer = Caterer()self.caterer.setCuisine()self.musician = Musician()self.musician.setMusicType()class Hotelier(object):def __init__(self):print("Arranging the Hotel for Marriage? --")def __isAvailable(self):print("Is the Hotel free for the event on given day? ")return Truedef bookHotel(self):if self. __isAvailable():print("Registered the Booking\n\n")class Florist(object):def __init__(self):print("Flower Decorations for the Event? --")def setFlowerRequirements(self):print("Carnations, Roses and Lilies would be used for Decorations\n\n")class Caterer(object):def __init__(self):print("Food Arrangements for the Event --")def setCuisine(self):print("Chinese & Continental Cuisine to be served\n\n")class Musician(object):def __init__(self):print("Musical Arrangements for the Marriage --")def setMusicType(self):print("Jazz and Classical will be played\n\n")class You(object):def __init__(self):print("You:: Whoa! Marriage Arrangements? ? ! ! ! ")def askEventManager(self):print("You:: Let's Contact the Event Manager\n\n")em = EventManager()em.arrange()def __del__(self):print("You:: Thanks to Event Manager, all preparations done! Phew! ")you = You()
you.askEventManager()

代理模式 – 控制对象访问

代理通常就是一个介于寻求方和提供方之间的中介系统。寻求方是发出请求的一方,而提供方则是根据请求提供资源的一方。

先通过一个简单的例子来理解该模式。不妨以演员与他的经纪人为例,当制作公司想要找演员拍电影时,他们通常会与经纪人交流,而不是直接跟演员交流。

其中 Actor 是代理。对象 Agent 用于查看 Actor 是否正处于忙碌状态。如果 Actor 正忙,则调用 Actor().occupied() 方法;如果 Actor 不忙,则返回 Actor().available() 方法。

class Actor(object):def __init__(self):self.isBusy = Falsedef occupied(self):self.isBusy = Trueprint(type(self). __name__ , "is occupied with current movie")def available(self):self.isBusy = Falseprint(type(self). __name__ , "is free for the movie")def getStatus(self):return self.isBusyclass Agent(object):def __init__(self):self.principal = Nonedef work(self):self.actor = Actor()if self.actor.getStatus():self.actor.occupied()else:self.actor.available()if __name__ == '__main__':r = Agent()r.work()

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

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

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

行为由类 You(即客户端)来表示。该类提供了 make_payment() 方法。主题是 Payment 类。它是一个抽象基类,代表一个接口。具有一个 do_pay() 方法,该方法需要借助代理和真实主题来实现。

Bank 类提供了多个方法来处理付款。代理使用 setCard() 方法将借记卡详细信息发送给银行。由 Bank 类(通过 Payment 接口)实现的 do_pay() 方法实际上负责根据可用资金向商家付款。

DebitCard 类是此处的代理。当你想要付款时,它会调用 do_pay() 方法。DebitCard 类充当真实主题(银行)的代理。

from abc import ABCMeta, abstractmethodclass Payment(metaclass=ABCMeta):@abstractmethoddef do_pay(self):passclass Bank(Payment):def __init__(self):self.card = Noneself.account = Nonedef __getAccount(self):self.account = self.card # Assume card number is account numberreturn self.accountdef __hasFunds(self):print("Bank:: Checking if Account", self. __getAccount(), "has enough funds")return Truedef setCard(self, card):self.card = carddef do_pay(self):if self. __hasFunds():print("Bank:: Paying the merchant")return Trueelse:print("Bank:: Sorry, not enough funds! ")return Falseclass 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()class You:def __init__(self):print("You:: Lets buy the Denim shirt")self.debitCard = DebitCard()self.isPurchased = Nonedef 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()

代理模式的优点:

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

门面模式和代理模式的比较

代理模式门面模式
为其他对象提供了代理或占位符,以控制对原始对象的访问为类的大型子系统提供了一个接口
代理对象具有与其目标对象相同的接口,并保存有目标对象的引用实现了子系统之间的通信和依赖性的最小化
充当客户端和被封装的对象之间的中介门面对象提供了单一的简单接口

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

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

相关文章

[手机Linux PostmarketOS]一,1加6T真正的手机Linux系统

前面用Linux deploy软件安装了Linux系统在手机,实则不是真正的手机刷成了linux系统,而是通过Linux deploy软件在容器里安装了Linux系统,在使用方面会有诸多限制,并不能发挥Linux的真实强大之处,于是我又百度又谷歌(真不…

Docker(四)-Docker镜像

1.概念 镜像是一种轻量级的、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖 打包好形成一个可交付的运行环境(包括代码,运行时需要的库,环境变量和配置文件等),这个打包好的运行环境…

记录锁为什么都加在索引上?

记录锁(Record Lock)加在索引上的原因主要与数据库的性能优化和数据一致性有关。具体来说,锁加在索引上而不是直接加在数据行上,有以下几个关键原因: 1. 提高查询效率 当锁加在索引上时,数据库可以更高效…

wireshark常见使用表达式

目录 1. 捕获过滤器 (Capture Filters)基本捕获过滤器组合捕获过滤器 2. 显示过滤器 (Display Filters)基本显示过滤器复杂显示过滤器协议特定显示过滤器 3. 进阶显示过滤器技巧使用函数和操作符逻辑操作符 4. 常见网络协议过滤表达式示例HTTP 协议HTTPS 协议DNS 协议DHCP 协议…

Scala入门教程

Scala入门教程可以按照以下步骤进行,以下是详细的内容分点表示和归纳: 一、Scala简介 Scala是一门多范式编程语言,融合了面向对象编程和函数式编程的特性。它运行在Java虚拟机(JVM)上,因此可以直接使用Ja…

项目经理究竟一年能挣多少钱?一起来看看

作为现代企业中不可或缺的职业之一,“项目经理”对于企业经营具有非常重要的作用。但是关于项目经理的待遇问题,却一直饱受争议。那么,项目经理一般年薪到底有多少钱呢? 一、项目经理年薪概述 根据行业调查和统计数据&#xff0…

【Java】三种实现网络通讯的方式以及相关协议的使用示例

Java网络 - 应用篇 👾以下代码均经过本人实测,请放心食用。顺便求个关注,谢谢!! 文章目录 Java网络 - 应用篇Socket 篇简介代码实现SockerServerSocketClient RestTemplate 篇简介...ForEntity 与 ...ForObject 对比示…

IPFoxy代理IP:IPv4与IPv6性能与安全性对比

在使用IPFoxy静态代理IP的过程中,经常有小白朋友疑惑,IPv4与IPv6有何区别?他们在性能与安全上的差别如何,又该如何选择?在这篇博文中,我们将从各个方面为您科普这一区别,帮助您更好的选择。 一、…

Bootstrap 间距实用类

Bootstrap 间距实用类(Spacing Utilities) Bootstrap 提供了一套强大的实用类,用于快速设置元素的 margin 和 padding。这些类名遵循一致的命名规则,支持响应式设计,可以在不同的视口尺寸上进行调整。 1. 基本概念 …

柒拾肆- 如何通过数据影响决策(五)- 时序数据

什么是好? 对于 单一时序指标 来说(如最简单的 销售、日活顾客数、订单数 等 ),在决策时该怎样 看 呢? 或者换句话说,数据 应该怎样 表达 才能让决策者做出 更全面 的决策呢? 一、目前的方式 …

MPC与DDP结合案例

MPC与DDP结合概要 MPC与DDP的关系 1. 相似性: 优化过程: 都涉及到优化一个代价函数以求得最优控制输入。动态模型: 都依赖于系统的动力学模型来预测和更新系统状态。2. 差异性: 时间尺度: MPC 是在线控制,每次只优化有限预测区间的控制输入,然后在每个时间步长重新优化。D…

Mkdocs中文系列教程补充(1)

什么是requirements.txt 我的理解是mkdocs依赖的py库 第一次建立MKdocs文档使用 mkdocs new . 完后,比较建议执行一下: pip install -r requirements.txt 不然mkdocs serve后会出现什么 xxx not found ,比如下面这位老哥 示例 mkdocs …

【C++】循环、控制流语句、

8、循环(loops)(1)for loops for循环非常灵活,可以做很多事情。上图红框框出来的代码块就是一个for循环。 for是关键字 for后面内容分为三部分,每部分用分号;隔开 第一部分A是变量的声明&…

Qt入门小项目 | 实现一个图片查看器

文章目录 一、实现一个图片查看软件 一、实现一个图片查看软件 需要实现的功能: 打开目录选择图片显示图片的名字显示图片 在以上功能的基础上进行优化,需要解决如下问题: 如何记住上次打开的路径? 将路径保存到配置文件中&#x…

使用MAT定位线上OOM问题

目录 1.什么是OOM? 2.发生的可能原因 3.常见类型的OOM 4.如何定位问题? 4.1 获取dump文件 4.2 MAT分析 「Leak Suspects」泄露嫌疑 「Histogram」直方图 「dominator tree」支配树 「thread overview」线程视图 目录 1.什么是OOM? 2.发生的可能原因 …

深度学习入门5——为什么神经网络可以学习?

在理解神经网络的可学习性之前,需要先从数学中的导数、数值微分、偏导数、梯度等概念入手,从而理解为什么神经网络具备学习能力。 1.数值微分的定义 先从导数出发理解什么是梯度。某一点的导数直观理解就是在该点的切线的斜率。在数学中导数表示某个瞬…

c#一个udp代码

不使用socket进行 unity下的 private Thread connectThread;private UdpClient udpClient;public Queue LogQueue new Queue();public static UDPManager Instance{get;private set;}private void Awake(){Instance this;}private void Start(){udpClient new UdpClient();…

dolphinscheduler独立集群部署文档(海豚调度)

一、下载解压 服务器内下载(华为云镜像站网址): wget https://mirrors.huaweicloud.com/apache/dolphinscheduler/3.2.0/apache-dolphinscheduler-3.2.0-bin.tar.gz解压:tar -xvf apache-dolphinscheduler-3.2.0-bin.tar.gz 改名…

05-对混合app应用中的元素进行定位

本文介绍对于混合app应用中的元素如何进行定位。 一、app的类型 1)Native App(原生应用) 原生应用是指利用Android、IOS平台官方的开发语言、开发类库、工具等进行开发的app应用,在应用性能和交互体验上应该是最好的。 通俗点来…