共享之道——享元模式(Python实现)

共享之道——享元模式(Python实现)

大家好,今天我们继续来讲结构型设计模式,上一期我们介绍了外观模式,这一期我们来讲享元模式(Flyweight Pattern)。

享元模式(Flyweight Pattern)是一种用于减少内存使用的设计模式,它通过共享尽可能多的数据来减少内存消耗;特别是当程序中存在大量相似对象时,享元模式非常有效。享元模式的核心思想是将那些相似的对象共享起来,避免重复创建相同或相似的对象,从而节省内存和资源,单例模式可以算是享元模式的一种特例。

享元模式简介

享元模式(Flyweight Pattern)是一种用于减少内存使用的设计模式,它通过共享尽可能多的数据来减少内存消耗;特别是当程序中存在大量相似对象时,享元模式非常有效。享元模式的核心思想是将那些相似的对象共享起来,避免重复创建相同或相似的对象,从而节省内存和资源。

享元模式的结构

享元模式通常包括以下几个部分:

  1. Flyweight:享元接口或抽象类,定义了对象的外部状态接口;
  2. ConcreteFlyweight:具体享元类,实现享元接口,并存储内部状态;
  3. FlyweightFactory:享元工厂类,用于创建和管理享元对象,确保合理地共享对象;
  4. Client:客户端类,维护外部状态并使用享元对象。
UML图

../_images/Flyweight.jpg

示意图

享元设计模式

享元模式的Python实现及实际应用

为了更好地理解享元模式,我们来看一个复杂的实际应用场景——假设我们正在开发一个大型多人在线游戏,需要显示大量的游戏角色,每个角色对象包含角色本身(内部状态)和位置、动作、装备等属性(外部状态)。使用享元模式可以显著减少内存消耗,因为相同的角色状态可以共享,以下是享元模式在Python中的一个实现示例:

class GameCharacterFlyweight:def __init__(self, character_type, model):self.character_type = character_typeself.model = modeldef render(self, position, action, equipment):print(f"Rendering character of type '{self.character_type}' with model '{self.model}' at position {position} with action {action} and equipment {equipment}")class CharacterFactory:def __init__(self):self.characters = {}def get_character(self, character_type, model):key = (character_type, model)if key not in self.characters:self.characters[key] = GameCharacterFlyweight(character_type, model)print(f"Creating new game character flyweight for '{character_type}' with model '{model}'")else:print(f"Reusing existing game character flyweight for '{character_type}' with model '{model}'")return self.characters[key]# 客户端代码
factory = CharacterFactory()characters = [("Warrior", "Model1", (10, 10), "Attack", "Sword"),("Mage", "Model2", (20, 20), "Cast Spell", "Staff"),("Warrior", "Model1", (30, 30), "Defend", "Shield"),("Mage", "Model2", (40, 40), "Teleport", "None"),("Warrior", "Model3", (50, 50), "Charge", "Axe"),("Archer", "Model4", (60, 60), "Shoot", "Bow"),("Mage", "Model2", (70, 70), "Heal", "Potion")
]for character_type, model, position, action, equipment in characters:character = factory.get_character(character_type, model)character.render(position, action, equipment)

在这个例子中:

  • GameCharacterFlyweight类表示共享的游戏角色对象,包含角色类型和模型等内部状态;
  • CharacterFactory类负责管理和创建这些共享对象,确保同类型同模型的角色对象共享;
  • 客户端代码展示了如何使用享元模式来渲染游戏角色,从而显著减少内存消耗。

享元模式的优缺点

优点:

  1. 减少内存使用:通过共享相似对象,显著减少内存消耗,这在需要创建大量相似对象的场景中尤为重要;
  2. 提高性能:由于减少了对象的数量,可以提高系统的性能,尤其是在内存受限的环境中,这种优化效果尤为明显;
  3. 统一管理:享元工厂集中管理共享对象,使得对象的创建和销毁更加可控。

缺点:

  1. 实现复杂:需要将对象的状态分为内部和外部状态,增加了实现的复杂性,尤其是在处理复杂对象时,需要仔细设计内部和外部状态的划分;
  2. 可能带来线程安全问题:在多线程环境下,共享对象需要注意线程安全问题,需要确保多个线程同时访问共享对象时不会引起数据不一致的问题;
  3. 增加了维护成本:由于实现复杂性和线程安全问题,享元模式的代码维护成本也随之增加。

享元模式的应用场景

  1. 系统中存在大量相似对象,导致内存消耗较大:例如图形界面系统中的字符显示、地图应用中的地图元素、游戏中的角色等;
  2. 对象的大部分状态可以外部化,可以将其移出对象:即对象的状态可以分为共享的内部状态和不共享的外部状态;
  3. 应用程序不依赖于对象标识:即对象的标识可以由其他数据来代替,而不需要依赖于对象本身的唯一标识。

总结

享元模式通过共享对象来减少内存消耗,在需要创建大量相似对象的场景中非常有效;理解和应用享元模式可以显著提高程序的性能和资源利用率,在实际项目中,正确识别和应用享元模式的场景,可以使系统更加高效和可维护。

希望本文能帮助你更好地理解享元模式及其在Python中的实现,并能在实际项目中灵活应用这一设计模式!如果你有任何疑问或想法,欢迎在下方留言!别忘了关注我们的公众号,获取更多有趣的编程知识和实用的代码技巧,我们期待与你的交流与分享!
在这里插入图片描述

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

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

相关文章

Bitwise 首席投资官:忽略短期的市场波动,关注加密货币的发展前景

原文标题:《The Crypto Market Sell-Off: What Happened and Where We Go From Here》撰文:Matt Hougan,Bitwise 首席投资官编译:Chris,Techub News 加密货币市场在周末经历了大幅下跌。从上周五下午 4 点到周一早上 7…

优质电器/机械岗位推荐:经验不限大厂直招,薪资最高30K!

本周优质电器/机械岗位推荐,涵盖C、自动化、开发、安卓开发、项目管理等岗位,经验不限,更有大厂直招岗位,薪资最高30K!! 抓紧投递,早投早入职! 👇点击职位名称查看详情…

PHP + Laravel + RabbitMQ + Redis 实现消息队列 (三) 消费队列在RabbitMQ和redis中的发布和订阅

发布订阅(Pub/Sub) 对于消息队列传统的模式来说,一个消费者消费一条消息,这条消息被消费之后就不会再次被其它的消费者消费。但是在发布订阅模式中,一条消息是可以被多个消费者消费的,这些消费者其实相当于…

前端构建工具|vite快速入门

认识vite vite组成部分 Vite是一种新型前端构建工具,能够显著提升前端开发体验。它主要由两部分组成: 一个开发服务器,它基于 原生 ES 模块 提供了 丰富的内建功能,如速度快到惊人的 模块热更新(HMR)。一…

C++——类模板经典案例——自定义通用数组类

案例:自定义数组类 需求: 1,对内置数据及自定义数据类型的数据存储 2,将数组中的数据存储到堆区 3,构造函数中可以存入数组的容量 4,提供对应的拷贝构造函数和运算符重载防止浅拷贝问题的发生 5&#xff0c…

基于Springboot + Vue的宿舍管理系统

前言 文末获取源码数据库 感兴趣的可以先收藏起来,需要学编程的可以给我留言咨询,希望帮助更多的人 精彩专栏推荐订阅 不然下次找不到哟 Java精品毕设原创实战项目 作者的B站地址:程序员云翼的个人空间-程序员云翼个人主页-哔哩哔哩视频 csd…

vue3+axios请求导出excel文件

在Vue 3中使用axios请求导出Excel文件,可以发送一个GET或POST请求,并设置响应类型为blob或arraybuffer,然后使用new Blob()构造函数创建一个二进制文件,最后使用URL.createObjectURL()生成一个可以下载的链接。 先看代码 import…

Stable Diffusion绘画 | 必备插件安装推荐

新手必备安装的插件推荐如下: 汉化语言包:汉化插件GitHub地址;双语对照插件GitHub地址无边图库:无边图库插件GitHub地址ControlNet:已默认安装 插件安装 最推荐的安装方式:通过「可下载」、「从网址安装…

Qt Modbus 寄存器读写实例

一.线圈状态寄存器读写 项目效果如下 1. 写单个寄存器 MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status); int addrui->spinBoxwirte_addr->value();int dataui->spinBoxwirte_data->value();int ret modbus_write_bit(mb,addr,d…

学习c#-4语句 ,条件,循环

代码: string name "小赵"; //条件判断 if (name "小赵") { Console.WriteLine("我是小赵"); } else { Console.WriteLine("我不是小赵"); } // switch条件判断 switch (name) { case "小…

5.3 匿名函数:Python编程中的隐士大师

欢迎来到我的博客,很高兴能够在这里和您见面!欢迎订阅相关专栏: 工💗重💗hao💗:野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典:收集整理全网各大IT互联网公司技术、项目、HR面试真题.…

嵌入式初学-C语言-十七

#接嵌入式初学-C语言-十六# 函数的递归调用 含义: 在一个函数中直接或者间接调用了函数本身,称之为函数的递归调用 // 直接调用a()->a(); // 间接调用a()->b()->a();a()->b()->..->a();递归调用的本质: 本是是一种循环…

【QT】Qt 音视频

Qt 音视频 Qt 音视频1. Qt 音频2. Qt 视频 Qt 音视频 在 Qt 中,音频主要是通过 QSound 类来实现。但是需要注意的是 QSound 类只支持播放 wav 格式的音频文件。也就是说如果想要添加音频效果,那么首先需要将非 wav 格式的音频文件转换为 wav 格式。 通…

JavaWeb之servlet关于Ajax实现前后端分离

一、什么是Ajax: AJAX Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。 AJAX 不是新的编程语言,而是一种使用现有标准的新方法。 AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部…

Nuxt2:强制删除window.__NUXT__中的数据

一、问题描述 在以前的一篇文章《Nuxt3: 强制删除__NUXT_DATA__的一种方式》中曾介绍了在Nuxt3中如何删除存在于页面id为__NUXT_DATA__的script节点中的数据。 此次,Nuxt2与Nuxt3不同在于它的数据是存在于window.__NUXT__,那么该如何处理呢?…

2025深圳国际户外庭院营地用品博览会

2025深圳国际户外庭院营地用品博览会 2025 Shenzhen International Outdoor Courtyard Camping Supplies Expo 时间:2025年02月27-3月01日 地点:深圳会展中心(福田馆) 详询主办方陆先生 I38(前三位) …

如何用OceanBase与DataWorks,打造一站式的数据集成、开发和数据服务

导语:在OceanBase 2024年开发者大会的技术生态论坛上,阿里云DataWorks团队的高级技术专家罗海伟,详细阐述了一站式大数据开发治理平台DataWorks的能力,并对于如何基于OceanBase和Dataworks构建一站式数据集成、开发以及数据服务进…

Linux驱动开发—Linux内核定时器概念和使用详解,实现基于定时器的字符驱动

文章目录 内核定时器概念在Linux驱动模块中使用定时器软定时器(Soft Timers)jiffies 含义高精度定时器(High Resolution Timers) 实现倒计时字符设备驱动 内核定时器概念 在 Linux 内核中,定时器是用来管理和调度延迟…

8.7-主从数据库的配置+mysql的增删改查

一、mysql环境的配置 1.环境准备 (1)主数据库 #关闭防火墙 [rootmaster ~]# systemctl stop firewalld#关闭selinux [rootmaster ~]# setenforce 0#下载lrzsz工具 [rootmaster ~]# yum -y install lrzsz#安装rsync [rootmaster ~]# yum -y install rs…

低代码平台:效率利器还是质量妥协?

目录 低代码平台:效率利器还是质量妥协? 一、引言 二、低代码平台的定义和背景 1、什么是低代码平台? 2、低代码平台的兴起 三、低代码开发的机遇 1、提高开发效率 2、降低开发成本 3、赋能业务人员 四、低代码开发的挑战 1、质量…