装饰器设计模式是什么?什么是 Decorator 装饰器设计模式?Python 装饰器设计模式示例代码

什么是 Decorator 装饰器设计模式?

装饰器模式是一种结构型设计模式,它允许向现有对象动态地添加新功能,同时不改变其结构。这种模式实现了对对象的包装,称为装饰器,并且可以在运行时动态地添加、修改或删除对象的行为。

在这里插入图片描述

主要思想:

装饰器模式允许你通过将对象放入包含行为的特殊包装器对象中来为原始对象添加新功能,使得代码更灵活、可重用,并且遵循开放-封闭原则。

主要角色:

  1. Component(组件): 定义了一个对象接口,可以动态地为该对象添加职责。
  2. ConcreteComponent(具体组件): 实现了 Component 接口的具体对象,是被装饰的原始对象。
  3. Decorator(装饰器): 持有一个指向 Component 对象的引用,并定义一个与 Component 接口一致的接口。
  4. ConcreteDecorator(具体装饰器): 向组件添加新的功能。

在这里插入图片描述

工作流程:

  1. 创建一个 Component 接口以及其具体实现 ConcreteComponent。
  2. 创建一个装饰器类,实现与 Component 相同的接口,并持有一个 Component 对象作为其成员变量。
  3. 创建具体装饰器类,对装饰器类进行扩展,添加额外的功能。

优点:

  1. 灵活性和扩展性: 可以动态地向对象添加新的功能,而无需修改其结构。可以通过堆叠装饰器来组合不同的功能,实现更多的组合方式。

  2. 遵循开放-封闭原则: 可以在不修改现有代码的情况下,通过装饰器来扩展功能,遵循了开放-封闭原则,使得系统更易于扩展。

  3. 单一职责原则: 可以将不同的责任分配给不同的装饰器,使得每个装饰器只关注一个特定的功能,符合单一职责原则。

  4. 代码复用性: 装饰器可以被多个对象共享使用,提高了代码的复用性,避免了重复编写相似功能的代码。

缺点:

  1. 复杂性增加: 可能会导致类层次结构变得复杂,堆叠过多的装饰器可能会使代码难以理解和维护。

  2. 运行时影响: 在运行时动态地添加功能,可能会影响系统的性能,特别是堆叠过多的装饰器可能会增加函数调用的开销。

  3. 正确性和顺序: 装饰器的正确性和顺序是很重要的,装饰器的堆叠顺序可能会影响最终的结果,需要小心处理。

  4. 不适用所有情况: 装饰器并不适用于所有情况。有些情况可能会使用其他设计模式更为合适,需要根据具体情况进行选择。

总的来说,装饰器模式提供了一种灵活的方式来扩展对象的功能,但需要权衡其增加的复杂性和运行时的影响。在适当的情况下使用,能够有效地提高代码的可扩展性和可维护性。


Python 实现装饰器设计模式示例代码(一):

# Component 接口
class Coffee:def cost(self):pass# ConcreteComponent
class SimpleCoffee(Coffee):def cost(self):return 5# Decorator 装饰器类
class CoffeeDecorator(Coffee):def __init__(self, coffee):self._coffee = coffeedef cost(self):return self._coffee.cost()# ConcreteDecorator 具体装饰器类
class Milk(CoffeeDecorator):def cost(self):return self._coffee.cost() + 2class Sugar(CoffeeDecorator):def cost(self):return self._coffee.cost() + 1# 使用示例
coffee = SimpleCoffee()
print(coffee.cost())  # 输出:5coffee_with_milk = Milk(coffee)
print(coffee_with_milk.cost())  # 输出:7coffee_with_milk_and_sugar = Sugar(coffee_with_milk)
print(coffee_with_milk_and_sugar.cost())  # 输出:8

在这个示例中,Coffee 是组件接口,SimpleCoffee 是具体组件,CoffeeDecorator 是装饰器类,MilkSugar 是具体装饰器类。通过装饰器模式,可以动态地为咖啡对象添加不同的装饰(牛奶、糖),每个装饰器都可以增加价格。


Python 实现装饰器设计模式示例代码(二):

当处理网页生成时,可以使用装饰器模式来动态地添加不同的 HTML 样式和元素。

# Component 接口
class HTMLPage:def show(self):pass# ConcreteComponent
class BasicHTMLPage(HTMLPage):def show(self):return "Basic HTML Page"# Decorator 装饰器类
class HTMLDecorator(HTMLPage):def __init__(self, html_page):self._html_page = html_pagedef show(self):return self._html_page.show()# ConcreteDecorator 具体装饰器类
class BoldDecorator(HTMLDecorator):def show(self):return f"<b>{self._html_page.show()}</b>"class ItalicDecorator(HTMLDecorator):def show(self):return f"<i>{self._html_page.show()}</i>"# 使用示例
basic_page = BasicHTMLPage()
print(basic_page.show())  # 输出:Basic HTML Pagebold_page = BoldDecorator(basic_page)
print(bold_page.show())  # 输出:<b>Basic HTML Page</b>italic_bold_page = ItalicDecorator(bold_page)
print(italic_bold_page.show())  # 输出:<i><b>Basic HTML Page</b></i>

在这个示例中,HTMLPage 是组件接口,BasicHTMLPage 是具体组件,HTMLDecorator 是装饰器类,BoldDecoratorItalicDecorator 是具体装饰器类。通过装饰器模式,可以动态地为基本 HTML 页面添加不同的样式,比如加粗、斜体等。


使用装饰器设计模式时,需要注意哪些地方?

在使用装饰器设计模式时,需要留意以下几个方面:

  1. 继承关系: 装饰器模式通过继承实现,这可能导致类层次结构变得复杂。过多的装饰器可能会使代码难以理解和维护。

  2. 功能堆叠顺序: 装饰器的堆叠顺序很重要,可能会影响最终结果。确保装饰器按照正确的顺序应用,避免意外的行为。

  3. 适用性和灵活性: 装饰器模式并不适用于所有情况。在某些情况下,可能会使用其他模式更为合适,需要根据具体情况进行选择。

  4. 影响性能: 堆叠过多的装饰器可能会影响性能,特别是在对性能敏感的场景下。过多的装饰器会增加函数调用的开销。

  5. 单一职责原则: 确保每个装饰器只关注一个特定的功能。不要让装饰器变得过于复杂,应遵循单一职责原则。

  6. 可读性和维护性: 过多的装饰器可能会降低代码的可读性和维护性。建议在使用装饰器时保持代码简洁易懂。

  7. Python 特殊性: 在 Python 中,装饰器是一种语法糖,经常用于修饰函数。但使用装饰器时要注意其影响范围和作用域。

总的来说,装饰器模式是一种灵活且强大的模式,但需要谨慎使用,特别是在需要管理复杂装饰器堆叠和性能敏感的情况下。


本文就到这里了,感谢您的阅读 。别忘了点赞、收藏~ Thanks♪(・ω・)ノ 🍇

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

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

相关文章

重磅!这本30w人都在看的Python数据分析畅销书:更新了!

想学习python进行数据分析&#xff0c;这本《利用python进行数据分析》是绕不开的一本书。目前该书根据Python3.10已经更新到第三版。 Python 语言极具吸引力。自从 1991 年诞生以来&#xff0c;Python 如今已经成为最受欢迎的解释型编程语言。 pandas 诞生于2008年。它是由韦…

NX二次开发UF_CAM_set_clear_plane_data 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CAM_set_clear_plane_data Defined in: uf_cam_planes.h int UF_CAM_set_clear_plane_data(tag_t object_tag, double origin [ 3 ] , double normal [ 3 ] ) overview 概述 De…

快慢指针判断环形链表

我们在前面文章中写过用快慢指针判断链表是否带环&#xff1a; leetcode&#xff1a;环形链表-CSDN博客 我们用的是slow指针一次走一步&#xff0c;fast指针一次走两步&#xff0c;当slow入环后开始了追击&#xff0c;每走一次距离缩短1&#xff0c;最终就会相遇 思考问题 …

【LeetCode】每日一题 2023_11_23 HTML 实体解析器(调库/打工)

文章目录 刷题前唠嗑题目&#xff1a;HTML 实体解析器题目描述代码与解题思路 结语 刷题前唠嗑 题目&#xff1a;HTML 实体解析器 题目链接&#xff1a;1410. HTML 实体解析器 题目描述 代码与解题思路 func entityParser(s string) (ans string) {return strings.NewRepla…

NX二次开发UF_CAM_set_lower_limit_plane_tag 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CAM_set_lower_limit_plane_tag Defined in: uf_cam_planes.h int UF_CAM_set_lower_limit_plane_tag(tag_t object_tag, tag_t target_tag ) overview 概述 Set the tag of a …

使用 PowerShell 创建共享目录

在 Windows 中&#xff0c;可以使用共享目录来将文件和文件夹共享给其他用户或计算机。共享目录可以通过网络访问&#xff0c;这使得它们非常适合用于文件共享、协作和远程访问。 要使用 PowerShell 创建共享目录&#xff0c;可以使用 New-SmbShare cmdlet。New-SmbShare cmdl…

算法的奥秘:常见的六种算法(算法导论笔记2)

算法的奥秘&#xff1a;种类、特性及应用详解&#xff08;算法导论笔记1&#xff09; 上期总结算法的种类和大致介绍&#xff0c;这一期主要讲常见的六种算法详解以及演示。 排序算法&#xff1a; 排序算法是一类用于对一组数据元素进行排序的算法。根据不同的排序方式和时间复…

postman定义公共函数这样写,测试组长直呼牛逼!!!

postman定义公共函数 在postman中&#xff0c;如下面的代码&#xff1a; 1、返回元素是否与预期值一致 var assertEqual(name,actual,expected)>{tests[${name}&#xff1a;实际结果&#xff1a; ${actual} &#xff0c; 期望结果&#xff1a;${expected}]actualexpected…

2023年危险化学品经营单位主要负责人证模拟考试题库及危险化学品经营单位主要负责人理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年危险化学品经营单位主要负责人证模拟考试题库及危险化学品经营单位主要负责人理论考试试题是由安全生产模拟考试一点通提供&#xff0c;危险化学品经营单位主要负责人证模拟考试题库是根据危险化学品经营单位主…

【追求卓越12】算法--堆排序

引导 前面几节&#xff0c;我们介绍了有关树的数据结构&#xff0c;我们继续来介绍一种树结构——堆。堆的应用场景有很多&#xff0c;比如从大量数据中找出top n的数据&#xff1b;根据优先级处理网络请求&#xff1b;这些情景都可以使用堆数据结构来实现。 什么是堆&#xf…

【20年扬大真题】编写程序,功能是计算1~10之间的偶数之和

【20年扬大真题】 编写程序&#xff0c;功能是计算1~10之间的偶数之和 #include<stdio.h> int main() {int i 1;int sum 0;for (i 1;i < 10;i){if (i % 2 0){sum i;}}printf("%d", sum); }

Java核心知识点整理大全9-笔记

目录 null文章浏览阅读9w次&#xff0c;点赞7次&#xff0c;收藏7次。Java核心知识点整理大全https://blog.csdn.net/lzy302810/article/details/132202699?spm1001.2014.3001.5501 Java核心知识点整理大全2-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全3-笔记_希斯…

FindMy技术用于充电宝

充电宝是一种便捷的充电器&#xff0c;方便个人随身携带&#xff0c;能够自行储备电能&#xff0c;为主流电子设备提供充电服务。它广泛应用于没有外部电源供应的场所&#xff0c;例如旅行、户外活动或紧急情况下&#xff0c;为用户的手持设备提供持续的电力支持&#xff0c;确…

spring boot加mybatis puls实现,在新增/修改时,对某些字段进行处理,使用的@TableField()或者AOP @Before

1.先说场景&#xff0c;在对mysql数据库表数据插入或者更新时都得记录时间和用户id 传统实现有点繁琐&#xff0c;这里还可以封装一下公共方法。 2.解决方法&#xff1a; 2.1&#xff1a;使用aop切面编程&#xff08;记录一下&#xff0c;有时间再攻克&#xff09;。 2.1.1&am…

centos 安装k8s教程(一键安装k8s)

第一步 准备几台机器 第二步 K8s Manager 服务器中添加docker支持 安装教程请查看这个博客 docker 安装详细教程 点我 第三步安装 KuboardSpray 教程在这里 第四步 下载k8s资源包 第五步 安装k8s 点击安装后 显示如下&#xff1a;等待完成

arduino入门一:点亮第一个led

void setup() { pinMode(12, OUTPUT);//12引脚设置为输出模式 } void loop() { digitalWrite(12, HIGH);//设置12引脚为高电平 delay(1000);//延迟1000毫秒&#xff08;1秒&#xff09; digitalWrite(12, LOW);//设置12引脚为低电平 delay(1000); }

电脑桌面便签工具选择哪一款?

随着互联网时代的不断发展&#xff0c;电脑成为日常工作及办公中必不可少的工具&#xff0c;通过电脑这款工具&#xff0c;大家可以更好的进行工作、学习等方面的交流&#xff1b;电脑桌面便签由于可以为大家整合一些工作及学习方面的备忘事项及笔记等&#xff0c;因而深受大家…

【Vue】Node.js的下载安装与配置

目录 一.下载安装 官网&#xff1a; 二.环境变量的配置 三.设置全局路径和缓存路径 四.配置淘宝镜像 五.查看配置 六.使用npm安装cnpm ​ 一.下载安装 官网&#xff1a; https://nodejs.org/en/download 下载完之后&#xff0c;安装的时候一直点next即可&#xff0c…

FlinkCDC实现主数据与各业务系统数据的一致性(瀚高、TIDB)

文章末尾附有flinkcdc对应瀚高数据库flink-cdc-connector代码下载地址 1、业务需求 目前项目有主数据系统和N个业务系统,为保障“一数一源”,各业务系统表涉及到主数据系统的字段都需用主数据系统表中的字段进行实时覆盖,这里以某个业务系统的一张表举例说明:业务系统表Ta…

CSGO游戏搬砖市场下跌分析,是跑还是入?

CSGO市场下跌分析&#xff0c;是跑还是入&#xff1f; 以下所有都是阿阳本人最近几年观察市场和踩坑的一点经验&#xff0c;由于篇幅不长所以肯定会很浅薄&#xff0c;大伙下嘴轻点 。 首先现在真的是CSGO市场最低点吗&#xff1f;后续还会跌吗&#xff1f;我们究竟是该继续观…