【八】python装饰器模式
文章目录
- 8.1 装饰器模式简介
- 8.2 装饰器模式作用
- 8.3 装饰器模式构成
- 8.3.1 装饰器模式包含以下几个核心角色:
- 8.3.2 UML类图
- 8.4 装饰器模式python代码实现
- 8.4.1 基本装饰器的使用
- 8.4.2 多个装饰器的执行顺序
- 8.4.3 带返回值的装饰器的使用
- 8.4.4 装饰器模式-关联类模式
- 8.4.5 装饰器模式-无参数
- 8.4.6 装饰器模式-接收原函数参数
- 8.4.7 装饰器模式-装饰器自带函数
- 8.4.8 装饰器模式应用-事务提交与回滚
- 8.5 装饰器模式优点与缺点
8.1 装饰器模式简介
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
装饰器模式通过将对象包装在装饰器类中,以便动态地修改其行为。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
8.2 装饰器模式作用
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决的问题:主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
8.3 装饰器模式构成
8.3.1 装饰器模式包含以下几个核心角色:
- 抽象组件(Component):定义了原始对象和装饰器对象的公共接口或抽象类,可以是具体组件类的父类或接口。
- 具体组件(Concrete Component):是被装饰的原始对象,它定义了需要添加新功能的对象。
- 抽象装饰器(Decorator):继承自抽象组件,它包含了一个抽象组件对象,并定义了与抽象组件相同的接口,同时可以通过组合方式持有其他装饰器对象。
- 具体装饰器(Concrete Decorator):实现了抽象装饰器的接口,负责向抽象组件添加新的功能。具体装饰器通常会在调用原始对象的方法之前或之后执行自己的操作。
装饰器模式通过嵌套包装多个装饰器对象,可以实现多层次的功能增强。每个具体装饰器类都可以选择性地增加新的功能,同时保持对象接口的一致性。
8.3.2 UML类图

8.4 装饰器模式python代码实现
8.4.1 基本装饰器的使用
import time#装饰器函数
def cont_time(func):def inner():start_time = time.time()print("计时开始")func()end_time = time.time()print('计时结束,耗时{:.2f}秒'.format(end_time-start_time))return inner#功能函数
@cont_time # 相当于do_work = cont_time(do_work)
def do_work():print('do work开始')time.sleep(1)print('do work结束')return 'work is done'res = do_work()
print(res)"""结果如下:
计时开始
do work开始
do work结束
计时结束,耗时1.01秒
None
"""
8.4.2 多个装饰器的执行顺序
def decorator1(func):print("执行装饰器1")def wrapper():print("在装饰器1中执行前")func()print("在装饰器1中执行后")return wrapper
def decorator2(func):print("执行装饰器2")def wrapper():print("在装饰器2中执行前")func()print("在装饰器2中执行后")return wrapper
@decorator1
@decorator2
def my_function():print("函数执行")my_function()
8.4.3 带返回值的装饰器的使用
import time#装饰器函数
def cont_time(func):def inner():start_time = time.time()print("计时开始")res = func() #在这里接收end_time = time.time()print('计时结束,耗时{:.2f}秒'.format(end_time-start_time))return resreturn inner#功能函数
@cont_time # 相当于do_work = cont_time(do_work)
def do_work():print('do work开始')time.sleep(1)print('do work结束')return 'work is done'res = do_work()
print(res)"""结果如下:
计时开始
do work开始
do work结束
计时结束,耗时1.01秒
None
"""
8.4.4 装饰器模式-关联类模式
# encoding: utf-8"""
装饰模式包含以下4个角色: Component(抽象构件) ConcreteComponent(具体构件)Decorator(抽象装饰类) ConcreteDecorator(具体装饰类)"""
# 抽象构建,原有产品的功能抽象
class Component(object):def operation(self):raise NotImplementedError#具体构件,就是被装饰的类,继承抽象组件
class ConcreteComponent(Component):def operation(self):print('车在地上跑')#抽象装饰类,和被装饰的类共同继承抽象组件,在这里重写抽象类中的方法,改变被装饰类的行为
class Decorator(Component):def __init__(self):self._component = Nonedef set_component(self,component):self._component = componentdef operation(self):if self._component is not None:self._component.operation()#具体装饰类A,给汽车扩展一个水里跑的功能
class ConcreteDecoratorA(Decorator):def __init__(self):super(ConcreteDecoratorA,self).__init__()def operation(self):super(ConcreteDecoratorA,self).operation()print('车在水里跑')
# 具体装饰类B
class ConcreteDecoratorB(Decorator):def operation(self):super(ConcreteDecoratorB,self).operation()self._add_behavior()# print('具体装饰对象B的操作')def _add_behavior(self):print('车在天上跑')if __name__ == '__main__':# 原有的汽车功能,只能地上跑c = ConcreteComponent()#被A装饰器装饰后,扩展水里跑的功能d1 = ConcreteDecoratorA()# 继续被B装饰器装饰后,扩展天上跑功能d2 = ConcreteDecoratorB()d1.set_component(c)d2.set_component(d1)d2.operation()
8.4.5 装饰器模式-无参数
# 装饰器--无参数
import time# 装饰器,记录函数运行时间
def decorator01(fun):def wapper():print('装饰器开始运行')stime = time.time()print('开始运行原函数')fun()etime = time.time()print('原函数结束')print("原函数运行时间: {TIME}".format(TIME=etime - stime))print('装饰器结束')return wapper # 必须要返回一个函数的内存地址# 使用装饰器装饰某个函数,等价于 test01=decorator01(test01),
# 即将test01实际引用变成wapper函数内存地址,所以执行test01实际是执行wapper
@decorator01
def test01():time.sleep(2)print("test01 运行")test01() # 不修改代码和调用方式,实现添加记录时间功能
8.4.6 装饰器模式-接收原函数参数
# 装饰器2-带参数
import time# 装饰器,记录函数运行时间
def decorator01(fun):def wapper(*args, **kwargs): # 使用非固定参数,无论参数是什么,都可以传递进来stime = time.time()fun(*args, **kwargs)etime = time.time()print("fun run time is {TIME}".format(TIME=etime - stime))return wapper # 必须要返回一个函数的内存地址# test01() = wapper(), 所以装饰器加参数是给嵌套函数加参数
@decorator01
def test01(args1):time.sleep(2)print("参数是 {NAME} ".format(NAME=args1))test01("参数示例") # 不修改代码和调用方式,实现添加记录时间功能
8.4.7 装饰器模式-装饰器自带函数
# 装饰器
import time# 如果装饰器有参数,最外层是装饰器的参数
def decorator01(*args, **kwargs):print("装饰器参数:", *args, **kwargs)def out(fun): # 第二层才是接受的函数def wapper(*args, **kwargs): # 使用非固定参数,无论参数是什么,都可以传递进来stime = time.time()fun(*args, **kwargs)etime = time.time()print("fun run time is {TIME}".format(TIME=etime - stime))return wapper # 必须要返回一个函数的内存地址return out # 要返回装饰函数的内存地址# 装饰器本身带参数,此时 decorator01(arg)=out,即相当于 @out装饰test01,所以 test01=out(fun)=wapper
@decorator01(5)
def test01(args1):time.sleep(2)print("参数是 {NAME} ".format(NAME=args1))test01("参数示例") # 不修改代码和调用方式,实现添加记录时间功能
8.4.8 装饰器模式应用-事务提交与回滚
在事务处理中,装饰器模式可以用于在执行数据库操作之前和之后执行一些附加的操作,例如日志记录、验证、事务管理等。下面是一个使用装饰器模式实现事务处理的示例:
class DatabaseOperation: """假设我们有一个数据库操作类 DatabaseOperation,它执行数据库的增、删、改、查操作。我们希望在执行这些操作时,先进行事务的开启,在操作完成后进行事务的提交或回滚。"""def __init__(self, operation): self.operation = operation def execute(self): try: # 开始事务 self.start_transaction() # 执行数据库操作 self.operation.execute() # 提交事务 self.commit_transaction() except Exception as e: # 发生异常时回滚事务 self.rollback_transaction() def start_transaction(self): # 实现事务开始的逻辑 pass def commit_transaction(self): # 实现事务提交的逻辑 pass def rollback_transaction(self): # 实现事务回滚的逻辑 passclass TransactionDecorator: """定义一个装饰器 TransactionDecorator,它接受一个数据库操作对象,并返回一个添加了事务处理逻辑的装饰器对象。""" def __init__(self, operation): self.operation = operation def execute(self): transaction = TransactionDecorator() transaction.start_transaction() try: self.operation.execute() transaction.commit_transaction() except Exception as e: transaction.rollback_transaction()#使用装饰器模式来执行带有事务处理的操作
@TransactionDecorator
class MyDatabaseOperation(DatabaseOperation): def __init__(self, operation): super().__init__(operation)
8.5 装饰器模式优点与缺点
- 优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
- 缺点:多层装饰比较复杂。
相关文章:
【八】python装饰器模式
文章目录 8.1 装饰器模式简介8.2 装饰器模式作用8.3 装饰器模式构成8.3.1 装饰器模式包含以下几个核心角色:8.3.2 UML类图 8.4 装饰器模式python代码实现8.4.1 基本装饰器的使用8.4.2 多个装饰器的执行顺序8.4.3 带返回值的装饰器的使用8.4.4 装饰器模式-关联类模式…...
Unity-小工具-LookAt
Unity-小工具-LookAt 🥙介绍 🥙介绍 💡通过扩展方法调用 gameObject.LookAtTarget,让物体转向目标位置 💡gameObject.StopLookat 停止更新 💡可以在调用时传入自动停止标记,等转向目标位置后自…...
TCP实现一对一聊天
一,创建类 二,类 1.ChatSocketServer类 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Sca…...
全面高压化与全面超快充,破解新能源汽车的时代难题
是什么让新能源车主感到疲惫与焦虑?是什么阻挡更多消费者选择新能源汽车?我们在身边进行一个简单的调查就会发现,问题的答案非常一致:充电。 充电难,充电慢的难题,始终是困扰新能源汽车产业发展,…...
02 CSS基础入门
文章目录 一、CSS介绍1. 简介2. 相关网站3. HTML引入方式 二、选择器1. 标签选择器2. 类选择器3. ID选择器4. 群组选择器 四、样式1. 字体样式2. 文本样式3. 边框样式4. 表格样式 五、模型和布局1. 盒子模型2. 网页布局 一、CSS介绍 1. 简介 CSS主要用于控制网页的外观&#…...
MyBatis框架中的5种设计模式总结
前言 MyBatis框架中使用的5种设计模式分别是:1、建造者模式(生成器模式)。2、工厂模式。3、单例模式。4、代理模式。5、适配器模式。 1、建造者模式(生成器模式) 在MyBatis环境的初始化过程中,SqlSessio…...
ffmpeg相关命令
视频转码 dav转化为mp4格式 ffmpeg -i 2021-08-10.dav -codec copy 11.mp4二进制文件转为mp4格式 // -c:v 指定视频流编码器,不指定编码会默认用mp4这种容器的默认音视频编码进入编码 // copy:不重新编码直接copy源视频流ffmpeg -i 1701687125-4fc72a…...
锂电3V升12V1A升压芯片WT3209
锂电3V升12V1A升压芯片WT3209 WT3209是一款高功率密度全集成BOOST升压转换器,具备高效能解决方案。3V升12V1A,5V升12V1A WT3209内部集成的功率MOSFET管导通电阻为上管13mΩ和下管11mΩ,具备2A开关电流能力,并且能够提供高达12.6V的输出电压。…...
Unity 置顶OpenFileDialog文件选择框
置顶文件选择框 🌭处理前🥙处理后 🌭处理前 🥙处理后 解决方案...
oomall课堂笔记
一、项目分层结构介绍 controller层(控制器层): 作用:负责输出和输入,接收前端数据,把结果返回给前端。 1.处理用户请求,接收用户参数 2.调用service层处理业务,返回响应 servi…...
Qt6.5类库实例大全:QFrame
哈喽大家好,我是20YC小二!欢迎扫码关注公众号,现在可免费领取《C程序员》在线视频教程哦! ~下面开始今天的分享内容~ 1. QFrame介绍 QFrame是Qt框架中的一个框架控件类,主要用于在图形用户界面(GUI)中创建框架&#…...
Java 数据结构篇-用数组、堆实现优先级队列
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 优先级队列说明 2.0 用数组实现优先级队列 3.0 无序数组实现优先级队列 3.1 无序数组实现优先级队列 - 入队列 offer(E value) 3.2 无序数组实现优先级队列 - 出…...
Reactor模型
目录 1.Reactor模型是什么2.Reactor 模型应用场景3.使用 Reactor 模型的软件4.Reactor 模型 与 Actor 模型 的关系 本文主要介绍Reactor模型基本概念以及应用场景。 1.Reactor模型是什么 Reactor模型是一种事件驱动的设计模式,用于处理服务请求,它是由…...
【SpringCloud】通过Redis手动更新Ribbon缓存来解决Eureka微服务架构中服务下线感知的问题
文章目录 前言1.第一次尝试1.1服务被调用方更新1.2压测第一次尝试1.3 问题分析1.4 同步的不是最新列表 2.第二次尝试2.1调用方过滤下线服务2.2压测第二次尝试2.3优化 写到最后 前言 在上文的基础上,通过压测的结果可以看出,使用DiscoveryManager下线服务…...
如何做好性能压测?压测环境设计和搭建的7个步骤你知道吗?
简介:一般来说,保证执行性能压测的环境和生产环境高度一致是执行一次有效性能压测的首要原则。有时候,即便是压测环境和生产环境有很细微的差别,都有可能导致整个压测活动评测出来的结果不准确。 1. 性能环境要考虑的要素 1.1 系…...
Qt12.13
...
目标检测YOLO系列从入门到精通技术详解100篇-【目标检测】SLAM(基础篇)(五)
目录 前言 几个相关概念 双目视惯雷达SLAM 相关工作 系统综述 视觉前端...
鸿蒙开发之页面与组件生命周期
一、页面间的跳转 创建文件的时候记得选择创建page文件,这样就可以在main->resources->profile->main_pages.json中自动形成页面对应的路由了。如果创建的时候你选择了ArkTS文件,那么需要手动修改main_pages.json文件中,添加相应的…...
Kotlin开发之低功耗蓝牙(引用三方库)的详解一
在我们工作中,如果涉及到软硬结合,经常会用到蓝牙,而蓝牙有两种:一种是普通的蓝牙,一种是低功耗的蓝牙,今天我们主要讲解的是低功耗蓝牙:主要根据第三方库进行的讲解 第一步:在使用…...
5G/4G工业DTU扬尘在线监测:解决工地扬尘困扰的最佳方案
在如今快速发展的工业环境中,扬尘污染成为了一个严重的问题。工地扬尘不仅对环境造成污染,还对工作人员的健康产生负面影响。为了解决这一问题,5G/4G工业DTU扬尘在线监测应运而生。 5G/4G工业DTU扬尘在线监测原理 5G/4G工业DTU扬尘在线监测是…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
