设计模式-09 - 享元模式 flyweight pattern

设计模式-09 - 享元模式  flyweight pattern

1.定义

享元模式是一种设计模式,它使用共享对象来减少内存使用和提高性能。它通过存储共享的对象实例池来实现,这些实例可以被多个客户端同时使用。

享元模式定义了一个接口,使客户端可以访问共享的轻量级对象。享元可以根据其内部状态进行细分,客户端只需要提供它需要的状态即可。享元对象被存储在共享池中,如果客户端请求一个已经存在的享元,则会返回该享元,否则会创建一个新的享元并将其添加到池中。

+--------------------+| Flyweight Factory  |+--------------------+|+--------------------+| Concrete Flyweight |+--------------------+|                    ||                    ||                    ||                    |+--------------------+|+--------------------------+| Context (with Flyweight) |+--------------------------+

说明:

  • Flyweight Factory:创建和管理享元对象。
  • Concrete Flyweight:实现享元接口的具体对象。享元对象是轻量级的、不可变的,并且具有大量重复实例。
  • Context:使用享元对象,并为其提供外部状态。
2.内涵

享元模式通常用于以下场景:

  • 当需要大量相同或相似对象时,例如在图形应用程序中表示图像或文本。
  • 当对象状态存储在外部数据结构中时,例如在数据库或缓存中。
  • 当对象创建或销毁成本很高时。

一个常见的享元模式示例是字符集中的字符对象。每个字符都可以表示为享元对象,其状态是字符的外观。当需要显示文本时,应用程序可以请求字符享元,而不需要为每个字符创建一个单独的对象。

享元模式与其他设计模式有一些相似之处:

  • 单例模式:享元模式与单例模式类似,因为它创建了一个共享对象,但享元模式允许创建多个共享对象。
  • 工厂方法模式:享元模式可以使用工厂方法模式来创建共享对象。
  • 策略模式:享元模式可以使用策略模式来存储对象的内部状态。

3.使用示例
#include <iostream>
#include <unordered_map>// Flyweight class
class Character {
public:Character(char intrinsicState) : m_intrinsicState(intrinsicState) {}void draw(int extrinsicState) {std::cout << "Drawing character '" << m_intrinsicState << "' at position " << extrinsicState << std::endl;}private:char m_intrinsicState;
};// Flyweight factory
class CharacterFactory {
public:Character* getCharacter(char key) {if (m_characters.find(key) == m_characters.end()) {m_characters[key] = new Character(key);}return m_characters[key];}private:std::unordered_map<char, Character*> m_characters;
};int main() {CharacterFactory characterFactory;// Extrinsic stateint position = 0;// Drawing characters 'A', 'B', 'C' at different positionscharacterFactory.getCharacter('A')->draw(position++);characterFactory.getCharacter('B')->draw(position++);characterFactory.getCharacter('C')->draw(position++);return 0;
}

4.注意事项


在使用享元模式时,需要注意以下事项:

  • 确定可共享的对象:并非所有对象都适合共享。只有当对象是轻量级的、不可变的并且具有大量重复实例时,才应考虑使用享元模式。
  • 管理对象状态:享元对象必须是不可变的,这意味着它们的状态一旦创建就不能被改变。如果对象需要可变状态,则可能需要使用其他设计模式,例如策略模式。
  • 处理并发性:如果多个客户端同时访问享元对象,则需要考虑并发性问题。可以使用同步机制来确保对象状态的一致性。
  • 避免过度共享:虽然共享对象可以减少内存使用,但过度共享可能会导致性能下降。只应共享真正需要的对象。
  • 考虑代码复杂性:享元模式可以引入一些代码复杂性,因为它需要管理共享对象池。在使用享元模式之前,应权衡收益和成本。
  • 其他注意事项:
  • 对象识别:享元对象需要一种方法来被客户端识别。这通常是通过使用唯一标识符或其他属性来实现的。
  • 外部状态:享元对象可以存储外部状态,但该状态不应修改享元对象本身。
  • 性能优化:为了优化享元模式的性能,应使用对象池来管理共享对象。对象池可以减少创建和销毁对象的开销。
  • 可测试性:享元模式的实现应可测试,以验证共享对象的正确性。可以使用单元测试来验证对象池的功能和共享对象的不可变性。
5.最佳实践


 
享元模式(Flyweight Pattern)最佳实践

1. 仅对可共享对象使用享元:

享元对象应是轻量级的、不可变的,并且具有大量重复实例。
2. 使用对象池管理共享对象:

对象池可以减少创建和销毁对象的开销,从而提高性能。
3. 确保对象不可变性:

享元对象的状态一旦创建就不能被改变。
4. 考虑并发性:

如果多个客户端同时访问享元对象,则需要考虑并发性问题。可以使用同步机制来确保对象状态的一致性。
5. 避免过度共享:

只应共享真正需要的对象。过度共享可能会导致性能下降。
6. 使用唯一标识符识别对象:

享元对象需要一种方法来被客户端识别。这通常是通过使用唯一标识符或其他属性来实现的。
7. 将外部状态存储在其他对象中:

享元对象可以存储外部状态,但该状态不应修改享元对象本身。
8. 使用单元测试验证共享对象的正确性:

单元测试可以验证对象池的功能和共享对象的不可变性。


6.总结


在使用享元模式时,应遵循设计原则,例如单一职责原则、开放/封闭原则和里氏替换原则。
通过遵循这些最佳实践,可以有效地使用享元模式来提高应用程序的性能和可维护性。

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

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

相关文章

安全关闭Tcp连接

close与shutdwon int close(int sockfd);关闭sokcet&#xff0c;这里注意&#xff1a;当程序调用close关闭socket的时候,如果缓冲区中仍然有数据的话,协议栈会发送RST包代替FIN包&#xff0c;丢弃缓冲的数据&#xff0c;强行关闭连接 int shutdown(int sockfd, int howto);该…

【Rollup】用rollup从0到1开发一个js插件并发布到npm

Rollup 是一个 JavaScript 模块打包器&#xff0c;专注于打包 ES6 模块将其编译回多种模块化格式&#xff0c;尤其适合打包库和框架&#xff0c;因为它可以生成更小、更高效的代码&#xff0c;并且特别适合将代码打包成可在浏览器中使用的库。 从0到1开发js插件 1.创建文件夹…

es终止快照恢复进程的方法

方法1、删除索引可以终止&#xff0c;恢复进程。 DELETE index_* // 按通配符删除以index_开头的索引 DELETE _all // 删除全部索引 POST *,-.*/_close 关闭索引 POST *,-.*/_open 打开索引 DELETE *,-.* 删除全部索引方法2、强制重启es 集群也可也终…

安全狗入选福建省网信系统2024年度网络安全技术支撑单位

近日&#xff0c;福建省委网信办会同国家互联网应急中心福建分中心确定并公示了福建省网信系统2024年度网络安全技术支撑单位名单。 作为国内云原生安全领导厂商&#xff0c;安全狗也成功入选。 据悉&#xff0c;此次遴选工作依据《中华人民共和国网络安全法》《国家网络安全事…

如何通过AI技术实现员工培训的革命性变革

AI个性化培训&#xff1a;开启员工潜力的新篇章 在当今这个信息爆炸的时代&#xff0c;人工智能&#xff08;AI&#xff09;技术的影响力已经渗透到社会的各个层面&#xff0c;包括教育与培训行业。AI技术正在彻底改变我们获取知识与技能的方式&#xff0c;特别是在员工培训领域…

IDEA使用技巧2—发布web项目

作者&#xff1a;私语茶馆 1.War包类型 发布Web项目有两种模式&#xff1a;war和war exploded&#xff0c; war模式&#xff1a;将WEB工程以包的形式上传到服务器 &#xff1b;war exploded模式&#xff1a;将WEB工程以当前文件夹的位置关系上传到服务器&#xff1b; war ex…

已解决java.lang.NoClassDefFoundError: 找不到类定义错误的正确解决方法,亲测有效!!!

已解决java.lang.NoClassDefFoundError: 找不到类定义错误的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 报错原因 解决思路 解决方法 检查类路径 确认类文件和库的位置 检查类加载器配置 确认依赖库的存在和版本 总结 问题…

解决NullPointerException at org.apache.hive.hcatalog.data.schema.HCatSchema.get问题

解决在org.apache.hive.hcatalog.data.schema.HCatSchema.get遇到NullPointerException 在使用hive sqoop import过程中遇到NullPointerExcetption at org.apache.hive.hcatalog.data.schema.HCatSchema.get 这大概率是导入hive的目标表结构与同步的column选项不匹配造成的。 …

c# 针对internal的类 如何写测试类

在C#中&#xff0c;internal 关键字意味着一个类型或成员只能在定义它的程序集中访问。这通常用于封装那些不应该被外部程序集直接访问的实现细节。但是&#xff0c;在编写单元测试时&#xff0c;我们可能希望测试这些internal类和方法。有几种方法可以实现这一点&#xff1a; …

用于视频识别的快慢网络

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;用于视频识别的快慢网络1、文献摘要2、提出方法2.1、SlowFast模型2.2、SlowFast 提出思想 3、相关方法3.1、时空间卷积3.2、基于光…

golang中变量交换的2种方式

变量的交换在我们对数据进行排序时是必须要用到的技术&#xff0c; 今天就给大家介绍2种go语言中交换变量的方式。 1. 使用传统方式定义一个中间变量来进行变量的交换 // 文件名 demo1.go package demo01import "fmt"func ExampleDemo02() {//常规方式进行变量交换…

词令蚂蚁庄园今日答案如何在微信小程序查看蚂蚁庄园今天问题的正确答案?

词令蚂蚁庄园今日答案如何在微信小程序查看蚂蚁庄园今天问题的正确答案&#xff1f; 1、打开微信&#xff0c;点击搜索框&#xff1b; 2、打开搜索页面&#xff0c;选择小程序搜索&#xff1b; 3、在搜索框&#xff0c;输入词令搜索点击进入词令微信小程序&#xff1b; 4、打开…

视频编辑软件pitivi基本功之创建标题片段

视频编辑软件pitivi基本功之创建标题片段 台式机的系统是openSUSE-Leap-15.5-DVD-x86_64 一、素材来源 《视频编辑软件pitivi基本功之使用SSR录制电脑屏幕》 https://blog.csdn.net/weixin_42145772/article/details/138597608?spm1001.2014.3001.5502 根据上面文章的方法得…

三层交换机与路由器连通上网实验

三层交换机是一种网络交换机&#xff0c;可以实现基于IP地址的高效数据转发和路由功能&#xff0c;通常用于大型企业、数据中心和校园网络等场景。此外&#xff0c;三层交换机还支持多种路由协议&#xff08;如OSPF、BGP等&#xff09;&#xff0c;以实现更为复杂的网络拓扑结构…

CCF CSP 认证考试历年真题满分题解(所有前四题)

CCF CSP 认证考试历年真题满分题解&#xff08;所有前四题&#xff09; 前言 原本刷题的动机仅仅是为研究生复试的机试环节做准备&#xff0c;我通过刷csp的真题来锻炼自己&#xff0c;因为上次的机试题目全部是csp真题&#xff0c;最后也是顺利上岸。空闲之际&#xff0c;我…

工业机器人应用实践之玻璃涂胶(篇三)

工业机器人 接上篇文章&#xff0c;浅谈一下实践应用&#xff0c;具体以玻璃涂胶为例&#xff1a; 了解工业机器人在玻璃涂胶领域的应用 认识工具坐标系的标定方法 掌握计时指令的应用 掌握人机交互指令的应用 掌握等待类指令用法&#xff08;WaitDI、WaitUnitl 等&#xff0…

练习题(2024/5/11)

1逆波兰表达式求值 给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意&#xff1a; 有效的算符为 、-、* 和 / 。每个操作数&#xff08;运算对象&#xff09;都可以是一个整数或…

【初阶数据结构】单链表基础OJ题讲解

前言 &#x1f4da;作者简介&#xff1a;爱编程的小马&#xff0c;正在学习C/C&#xff0c;Linux及MySQL。 &#x1f4da;本文收录与初阶数据结构系列&#xff0c;本专栏主要是针对时间、空间复杂度&#xff0c;顺序表和链表、栈和队列、二叉树以及各类排序算法&#xff0c;持…

创新指南 |风险管理:企业如何应对颠覆性创新带来的挑战

在当今充满变数的商业时代&#xff0c;颠覆性创新是企业突破传统、引领市场的关键。然而&#xff0c;真正的创新之旅并不平坦&#xff0c;充满了挑战和不确定性。文章将快速引导读者了解颠覆性创新的定义、挑战、以及如何通过设计思维、市场洞察、利益相关者沟通和文化变革等关…

一文带你看懂Vue.js

Vue.js&#xff08;发音为 /vjuː/&#xff0c;类似 view&#xff09;是一款用于构建用户界面的JavaScript框架。它基于标准HTML、CSS和JavaScript构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;可以高效地开发用户界面。无论是简单还是复杂的界面&#…