二十三种设计模式-享元模式

embedded/2025/1/31 13:20:57/

享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享相同对象来减少内存使用,尤其适合在大量重复对象的情况下。

核心概念

享元模式的核心思想是将对象的**可共享部分(内部状态)提取出来进行共享,而将不可共享部分(外部状态)**通过参数传递。这种方式可以显著减少内存占用,提高性能。

角色组成
  1. 抽象享元(Flyweight)
    定义了享元对象的接口,包含内部状态和外部状态的管理方法。

  2. 具体享元(Concrete Flyweight)
    实现了抽象享元接口,存储和管理内部状态。

  3. 享元工厂(Flyweight Factory)
    负责创建和管理享元对象,确保相同内部状态的对象只被创建一次。

  4. 非共享享元(Unshared Concrete Flyweight)
    不共享的部分,存储每个对象独立的状态。

应用场景

享元模式适用于以下场景:

  1. 大量相似对象的创建:当系统中存在大量相似对象,且这些对象占用大量内存时。

  2. 对象的共享性较强:对象的某些部分可以共享(如颜色、字体),而某些部分是特有的(如位置、大小)。

  3. 缓存场景:如数据库连接池、线程池等,通过共享技术减少内存占用。

优点

  1. 节省内存:通过共享对象,减少了内存中对象的数量。

  2. 提高性能:减少了对象创建和销毁的开销。

  3. 易于扩展:新的享元对象可以方便地加入系统。

缺点

  1. 实现复杂:需要维护共享对象的管理机制,增加了系统的复杂性。

  2. 线程安全问题:在多线程环境下,需要确保共享对象的线程安全。

实现示例

以下是一个简单的Java实现示例:

// 抽象享元类
interface Flyweight {void operation(String extrinsicState);
}// 具体享元类
class ConcreteFlyweight implements Flyweight {private String intrinsicState;public ConcreteFlyweight(String intrinsicState) {this.intrinsicState = intrinsicState;}@Overridepublic void operation(String extrinsicState) {System.out.println("Intrinsic State: " + intrinsicState + ", Extrinsic State: " + extrinsicState);}
}// 享元工厂类
class FlyweightFactory {private Map<String, Flyweight> flyweights = new HashMap<>();public Flyweight getFlyweight(String intrinsicState) {if (!flyweights.containsKey(intrinsicState)) {flyweights.put(intrinsicState, new ConcreteFlyweight(intrinsicState));}return flyweights.get(intrinsicState);}
}// 客户端代码
public class Client {public static void main(String[] args) {FlyweightFactory factory = new FlyweightFactory();Flyweight flyweight1 = factory.getFlyweight("A");Flyweight flyweight2 = factory.getFlyweight("B");Flyweight flyweight3 = factory.getFlyweight("A");flyweight1.operation("ClientState1");flyweight2.operation("ClientState2");flyweight3.operation("ClientState3");}
}

运行结果:

Intrinsic State: A, Extrinsic State: ClientState1
Intrinsic State: B, Extrinsic State: ClientState2
Intrinsic State: A, Extrinsic State: ClientState3

从输出可以看出,享元模式成功地实现了对相同对象的复用。

注意事项

  1. 合理划分内部状态和外部状态:内部状态存储在对象内部,外部状态通过参数传递。

  2. 享元对象的不可变性:享元对象应为不可变对象,避免线程安全问题。

  3. 权衡利弊享元模式虽然可以节省内存,但会增加系统的复杂性。需要根据具体场景权衡是否使用。

享元模式在实际项目中广泛应用于需要优化内存使用和提高性能的场景,如缓存系统、图形界面、文本编辑器等。

享元模式(Flyweight Pattern)适用于以下具体场景:

1. 大量相似对象的场景

当系统中存在大量相似对象时,可以使用享元模式来减少内存占用。例如:

  • 文本编辑器中的字符对象:文本编辑器中大量重复出现的字符对象可以使用享元模式来共享。每个字符对象的字体、大小等内部状态可以共享,而位置、颜色等外部状态则由客户端管理。

  • 围棋棋子:在围棋程序中,黑色和白色棋子可以共享,而棋子的位置则作为外部状态。

  • 象棋棋子:象棋程序中,棋子的颜色(黑色或白色)可以共享,而棋子的位置则作为外部状态。

2. 缓存场景

享元模式可以用于实现缓存,特别是在需要频繁访问、计算成本高昂的数据时。通过共享已计算好的数据,可以提高系统的性能。

3. 数据库连接池和线程池

在数据库连接池和线程池中,享元模式可以用于共享可用的连接或线程对象,避免频繁地创建和销毁,从而提高系统性能。

4. 图形处理和游戏开发

  • 图形对象共享:在图形处理中,例如绘制大量相似的圆形、矩形等图形对象时,可以通过享元模式共享图形的内部状态(如颜色、大小等),而将位置等外部状态传递给具体对象。

  • 在线游戏中的角色属性:游戏中大量玩家角色的不变属性(如名称、等级、经验值等)可以共享,而装备、技能等级等可变属性则单独存储。

5. 大数据处理

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

6. 性能和内存瓶颈问题

当应用程序遇到性能瓶颈,尤其是在内存使用上,享元模式可以通过复用对象来减轻内存压力。

7. 字符串常量池

Java中的字符串常量池是享元模式的一个经典应用。字符串常量池通过共享相同的字符串对象,减少了内存占用。

总结

享元模式适用于需要优化内存使用和提高性能的场景,特别是在系统中存在大量相似对象、对象创建和销毁成本较高、以及需要频繁访问和共享数据的情况下。然而,享元模式也会增加系统的复杂性,需要合理权衡其优缺点。


http://www.ppmy.cn/embedded/158359.html

相关文章

如何制作浪漫风格的壁纸

制作浪漫风格的壁纸需要营造出温馨、柔和、梦幻的氛围&#xff0c;通过色彩、元素和构图来传达浪漫的情感。以下是一个详细的步骤指南&#xff0c;帮助你制作浪漫风格的壁纸&#xff1a; 一、明确设计目标 确定用途&#xff1a; 个人使用&#xff1a;如果是为了个人设备&#…

每日 Java 面试题分享【第 15 天】

欢迎来到每日 Java 面试题分享栏目&#xff01; 订阅专栏&#xff0c;不错过每一天的练习 今日分享 3 道面试题目&#xff01; 评论区复述一遍印象更深刻噢~ 目录 问题一&#xff1a;Java 中的基本数据类型有哪些&#xff1f;问题二&#xff1a;什么是 Java 中的自动装箱和…

飞书项目流程入门指导手册

飞书项目流程入门指导手册 参考资料准备工作新建空间国际化配置新建工作项字段管理新建字段对接标识授权角色 流程管理基础说明流程节点配置流程节点的布局配置页面上布局按钮布局配置 流程节点驳回流程图展示自动化字段修改 局限性 参考资料 飞书官方参考文档&#xff1a;飞书…

关于 SR-IOV 架构论文的总结文章

关于 SR-IOV 架构论文的总结文章 在计算机虚拟化技术不断发展的进程中,SR - IOV 架构凭借其在提升 I/O 性能、优化资源利用等方面的优势,成为众多研究关注的焦点。通过对 4 篇相关论文的研读,我们可以从多个维度深入了解 SR - IOV 架构的核心要点。 一、SR - IOV 架构的原…

基于SpringBoot的高校志愿活动服务平台

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

java 正则表达式匹配Matcher 类

Matcher 类 用法 在 Java 中&#xff0c;Matcher 类是用于匹配正则表达式的工具&#xff0c;而 group() 方法是 Matcher 类中的一个重要方法&#xff0c;用于提取匹配结果中的捕获组&#xff08;captured groups&#xff09;。以下是对 group() 方法的详细解释&#xff1a; 1.…

【Python实现机器遗忘算法】复现2023年TNNLS期刊算法UNSIR

【Python实现机器遗忘算法】复现2023年TNNLS期刊算法UNSIR 1 算法原理 Tarun A K, Chundawat V S, Mandal M, et al. Fast yet effective machine unlearning[J]. IEEE Transactions on Neural Networks and Learning Systems, 2023. 本文提出了一种名为 UNSIR&#xff08;Un…

掌握Java反射:在项目中高效应用反射机制

1. 什么是Java反射&#xff1f; Java反射是一种非常强大的功能&#xff0c;允许程序在运行时动态地获取类的信息&#xff0c;甚至可以创建对象、调用方法和访问字段。简单来说&#xff0c;反射就像是让程序自己“看见”并操作自己&#xff0c;类似于自我检查和自我修改。 反射…