程序员必知!享元模式的实战应用与案例分析

程序员必知!享元模式的实战应用与案例分析 - 程序员古德

享元模式是一种减少相似对象创建和销毁的设计模式,通过将对象状态分为不变和可变部分,实现内存节省和性能提升。例如,在线游戏中大量玩家角色可共享相同的不变属性,而每人特有的可变属性则单独存储,享元模式使用享元类存储不变属性,非享元类存储可变属性,并通过享元工厂管理对象的复用和共享。

定义

程序员必知!享元模式的实战应用与案例分析 - 程序员古德

享元模式是一种对象设计模式,它用于减少大量相似对象(也称为“细粒度对象”)的创建和销毁,从而节省内存和提高性能。

享元模式的基本思想是将对象的内部状态分为两部分:不变部分和可变部分。不变部分包括所有对象共享的相同状态,而可变部分是每个对象特有的状态。通过将不变部分提取出来并存储在享元对象中,可以避免重复创建相同的对象,从而减少内存占用。

举一个简单的例子来说明享元模式的应用场景:假设当前正在开发一个在线游戏,游戏中有大量的玩家角色,每个角色都有相同的名称、等级和经验值等不变属性,但装备、技能等级等是每个角色特有的可变属性,在这种情况下,可以将玩家的不变属性存储在一个享元对象中,然后为每个角色分配一个可变属性的实例,这样,多个角色可以共享同一个享元对象,从而减少内存占用。

享元模式在实现时通常使用两个类:一个享元类(Flyweight)用于存储不变属性,另一个非享元类(Unshared)用于存储可变属性,通过享元工厂(FlyweightFactory)来管理享元对象的创建和销毁,以确保它们能够被正确地复用和共享。

代码案例

程序员必知!享元模式的实战应用与案例分析 - 程序员古德

以下是一个未使用享元模式的反例代码,这个例子中创建了大量的相似对象,导致消耗大量的内存和性能,如下代码:

// 未使用享元模式的反例代码  
public class Circle {  private double x;  private double y;  private double radius;  // 构造函数,每次调用都会创建一个新的Circle对象  public Circle(double x, double y, double radius) {  this.x = x;  this.y = y;  this.radius = radius;  }  // 绘制圆形的方法  public void draw() {  System.out.println("Circle: Draw() [x : " + x + ", y :" + y + ", radius :" + radius);  }  
}  // 客户端调用案例  
public class Client {  public static void main(String[] args) {  // 创建大量的Circle对象,这将消耗大量的内存和性能  for (int i = 0; i < 10; i++) {  Circle circle = new Circle(0, 0, 1); // 所有的圆都有相同的位置和半径  circle.draw();  }  }  
}

上面例子中,尽管所有的Circle对象都有相同的位置和半径,但仍然为每个对象分配了内存,如果需要创建数百万个这样的对象,那么内存消耗将是巨大的,此外,由于每个对象都需要被垃圾收集器处理,这也可能降低程序的性能。

如果使用享元模式,可以共享相同的Circle对象,从而大大减少内存消耗和提高性能,在享元模式中,通常会创建一个享元工厂来管理和重用对象,这样,即使需要大量的相似对象,也只需要存储它们的一个实例。

以下是一个使用享元模式的正例代码,在这个例子中,将使用享元模式来减少具有相同属性的Circle对象的创建,将会创建一个CircleFactory来管理Circle对象的创建和重用,如下代码:

// 享元模式中的抽象享元角色  
interface Shape {  void draw();  
}  // 享元模式中的具体享元角色  
class Circle implements Shape {  private final String color;  private final int x;  private final int y;  private final int radius;  // 构造函数私有化,因为外部的类不应该直接实例化这个类,而应该通过工厂来获取实例  private Circle(String color, int x, int y, int radius) {  this.color = color;  this.x = x;  this.y = y;  this.radius = radius;  }  @Override  public void draw() {  System.out.println("Circle: Draw() [Color : " + color + ", x : " + x + ", y :" + y + ", radius :" + radius + "]");  }  // 根据属性创建Circle的静态内部类,作为享元工厂的实现  private static class CircleFactory {  // 使用HashMap存储已经创建的Circle对象,实现重用  private static final Map<String, Circle> circleMap = new HashMap<>();  // 获取Circle对象的方法,如果Map中没有则创建一个新的Circle对象并存入Map中  public static synchronized Circle getCircle(String color, int x, int y, int radius) {  String key = color + x + y + radius; // 将属性和在一起作为key,确保相同的属性可以得到相同的对象  if (!circleMap.containsKey(key)) {  circleMap.put(key, new Circle(color, x, y, radius));  }  return circleMap.get(key); // 返回对应key的Circle对象,如果已经存在则直接重用  }  }  // 提供一个静态方法来获取Circle对象,客户端应该通过这个方法来获取Circle对象而不是直接new  public static Circle getCircle(String color, int x, int y, int radius) {  return CircleFactory.getCircle(color, x, y, radius);  }  
}  // 客户端调用案例  
public class Client {  public static void main(String[] args) {  // 通过享元工厂获取Circle对象,如果具有相同属性的对象已经存在,则直接重用该对象  for (int i = 0; i < 5; i++) {  Circle circle = Circle.getCircle("Red", 0, 0, 1); // 请求相同属性的圆形对象  circle.draw(); // 调用绘制方法,将看到是同一个对象被重用  }  System.out.println("------------------");  // 请求不同属性的圆形对象,将会创建新的对象实例  Circle anotherCircle = Circle.getCircle("Blue", 1, 1, 2);   anotherCircle.draw(); // 调用绘制方法,将看到是一个新的对象被创建并绘制  }  
}

在这个例子中,创建了一个Circle类来实现Shape接口,使用了一个私有的静态内部类CircleFactory来作为享元工厂,它使用一个HashMap来存储已经创建的Circle对象,客户端通过调用Circle.getCircle()方法来获取Circle对象,如果具有相同属性的对象已经存在于Map中,那么该方法将返回这个已经存在的对象,否则,它将创建一个新的对象并将其添加到Map中,这样,就可以重用具有相同属性的对象,从而减少内存消耗并提高性能。

核心总结

程序员必知!享元模式的实战应用与案例分析 - 程序员古德

享元模式是一种用于优化性能的设计模式,它通过共享相同或相似对象来减少系统中对象的数量,从而节省内存和提高效率,其优点在于能够显著减少对象创建和销毁带来的开销,特别适用于需要大量相似对象但状态可外部化的场景。然而,享元模式也有缺点,它增加了系统的复杂性,需要额外的逻辑来管理共享对象池,并可能导致状态同步问题。当存在明确需要优化对象数量和内存占用时再考虑使用,同时要仔细设计和管理共享对象池,确保状态的一致性和正确性。

其它应用场景补充

数据库连接池,数据库连接池是享元模式最经典的使用场景之一,在这个场景中,创建数据库连接对象需要消耗大量的资源,而且这些对象的内部状态大部分都是相同的,因此,可以通过享元模式来共享这些对象,减少对象的创建和销毁,提高系统的性能和可扩展性。

线程池,线程池也是享元模式的一个应用场景,线程的创建和销毁需要消耗大量的资源,而且线程的内部状态大部分都是相同的,因此,可以通过享元模式来共享线程对象,避免频繁地创建和销毁线程。

大数据处理,在处理大量数据时,可能会存在大量的重复对象,如图像处理中的像素点、文本处理中的单词等,这些对象可以通过享元模式来减少内存消耗和提高处理速度。

其它场景?

完!

关注我,每天学习互联网编程技术 - 程序员古德

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

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

相关文章

微信小程序-页面开发

文章目录 微信小程序第二章2. 页面开发2.1 创建开发页面2.2 修改项目首页2.3 页面的结构和样式设计2.3.1 WXML结构设计2.3.1.1 什么是WXML2.3.1.2 WXML的常见标签2.3.1.3 WXML的特点 2.3.2 WXSS样式设计2.3.2.1 什么是WXSS 2.4 组件库的使用和自定义组件2.4.1 小程序中的组件分…

企业特别大的文件用什么传输比较快?

在企业日常运营中&#xff0c;经常需要传输大文件&#xff0c;比如营销资料、设计图纸、视频素材等等&#xff0c;这些文件不仅大小可能达到几个GB甚至几个TB&#xff0c;而且往往需要跨越地域和网络环境进行传输&#xff0c;这就给企业带来了很大的挑战。 在企业内部&#xff…

高级感满满的视频监控技术?看完这骚操作,我震惊了!

随着科技的不断进步&#xff0c;视频监控系统在各个领域得到了广泛的应用。无论是保障公共安全、管理商业场所&#xff0c;还是监控生产流程&#xff0c;视频监控系统为我们提供了全面、实时的信息。 客户案例 零售业 在零售业中&#xff0c;实时监控对于防范盗窃、提升店内安…

whl is not a supported wheel on this platform.解决办法

1.问题&#xff1a; 安装torch产生 2.解决办法&#xff1a; 使用pip debug --verbose查看 对应的torch版本号 Compatible tags字样&#xff0c;这些就是当前Python版本可以适配的标签。例如&#xff0c;我的Python版本是3.11&#xff0c;可以匹配下面这些文件名&#xff1a;…

使用IDEA创建使用 JDK8 的 2.x.x 版本的 Spring Boot 项目以及 Spring Boot 项目如何修改JDK版本

目录 一、在阿里云上官网上创建项目 二、将 IDEA 中创建项目的源地址修改为阿里云官网 三、创建 3.x.x 的项目之后修改配置降低至 2.7.x 版本和使用 JDK8&#xff08;修改 Spring Boot 的 JDK 版本同理&#xff09; 从上面的 Spring Boot 官网的截图中可以发现&#xff0c;自…

【教学类-43-15】 20240103 (5宫格数独:内存数据不够计算) 不重复的基础模板数量:未知

背景需求&#xff1a; 测试5宫格有多少种不重复的基础模板&#xff08;只测试所有的25数字一组有多少个&#xff09; # 测试11*11格&#xff0c;2*2一共4套3*3 宫格目的&#xff1a;数独14 5宫格有不同的基础模板 作者&#xff1a;阿夏 时间&#xff1a;2024年01月04日 13:…

CSS免费在线字体格式转换器 CSS @font-face 生成器

今天竟意外发现的一款免费的“网页字体生成器”&#xff0c;功能强大又好用~ 工具地址&#xff1a;https://transfonter.org/ 根据你设置生成后的文件预览&#xff1a; 支持TTF、OTF、WOFF、WOFF2 或 SVG字体格式转换生成&#xff0c;每个文件最大15MB。转换完成以后还会生成一…

冠珠瓷砖携手时尚COSMOPOLITAN 对话时尚先锋,大美造境迭代筑家美学

冠珠瓷砖的三十年&#xff0c;是致力迭代中国人居大美的三十年&#xff1b;时尚COSMO的三十年&#xff0c;是探索女性美好生活的三十年&#xff1b;大美筑家先驱者遇上时尚美学潮流领航者&#xff0c;以一场充满美学张力的时尚跨界&#xff0c;献礼大美人居生活&#xff0c;致敬…

微信小程序 ---- 通过 URLScheme 或 URLLink 从短信、邮件、微信外网页等场景打开小程序

1. 用于短信、邮件、网页、微信内等拉起小程序的方法 《URL Scheme 拉起小程序》《URL Link 拉起小程序》 2. 功能描述 URL Scheme: 该接口用于获取小程序 scheme 码&#xff0c;适用于短信、邮件、外部网页、微信内等拉起小程序的业务场景。目前仅针对国内非个人主体的小程…

让设备更聪明 |启英泰伦离线自然说,开启智能语音交互新体验!

语音交互按部署方式可以分为两种&#xff1a;离线语音交互和在线语音交互。 在线语音交互是将数据储存在云端&#xff0c;其具备足够大的存储空间和算力&#xff0c;可以实现海量的语音数据处理。 离线语音交互是以语音芯片为载体&#xff0c;语音数据的采集、计算、决策均在…

2024年【煤炭生产经营单位(安全生产管理人员)】证考试及煤炭生产经营单位(安全生产管理人员)模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 煤炭生产经营单位&#xff08;安全生产管理人员&#xff09;证考试是安全生产模拟考试一点通总题库中生成的一套煤炭生产经营单位&#xff08;安全生产管理人员&#xff09;模拟考试题&#xff0c;安全生产模拟考试一…

Vue中的计算属性与监听器

聚沙成塔每天进步一点点 ⭐ 专栏简介 Vue学习之旅的奇妙世界 欢迎大家来到 Vue 技能树参考资料专栏!创建这个专栏的初衷是为了帮助大家更好地应对 Vue.js 技能树的学习。每篇文章都致力于提供清晰、深入的参考资料,让你能够更轻松、更自信地理解和掌握 Vue.js 的核心概念和技…