java23种设计模式-享元模式

devtools/2025/3/1 13:46:44/

享元模式(Flyweight Pattern)学习笔记

1. 模式定义

结构型设计模式,通过共享技术实现大量细粒度对象的复用,有效减少内存占用并提高性能。核心思想:分离内部状态(可共享)与外部状态(不可共享)

2. 适用场景

✅ 系统中存在大量相似对象

✅ 对象的大部分状态可以外部化

✅ 需要缓存池或对象池的应用

✅ 需要减少内存占用和提高性能的场景

3. 模式结构

creates
requests
FlyweightFactory
-pool: Map
+getFlyweight(key)
«interface»
Flyweight
+operation(extrinsicState)
ConcreteFlyweight
-intrinsicState
+operation(extrinsicState)
UnsharedConcreteFlyweight
-allState
+operation(extrinsicState)
Client
-flyweights: List
+addFlyweight()
+executeOperations()

4. 核心角色

角色说明
Flyweight抽象享元接口,定义操作接口
ConcreteFlyweight具体享元类,包含内部状态(可共享)
UnsharedConcreteFlyweight非共享具体享元类(可选)
FlyweightFactory享元工厂类,管理享元对象池
Client客户端,维护外部状态并调用享元对象

5. 状态说明

状态类型说明
内部状态存储在享元对象内部,可以被多个上下文共享的信息
外部状态随上下文变化的信息,由客户端保存并在调用时传入

6. 代码示例

6.1 文字编辑器字符对象

java">// 抽象享元
interface Character {void display(int x, int y, String color);
}// 具体享元
class ConcreteCharacter implements Character {private char symbol;  // 内部状态public ConcreteCharacter(char symbol) {this.symbol = symbol;}@Overridepublic void display(int x, int y, String color) {  // 外部状态System.out.printf("显示字符 %c 在(%d,%d),颜色:%s%n", symbol, x, y, color);}
}// 享元工厂
class CharacterFactory {private Map<Character, Character> pool = new HashMap<>();public Character getCharacter(char key) {if (!pool.containsKey(key)) {pool.put(key, new ConcreteCharacter(key));}return pool.get(key);}
}// 客户端
public class Client {public static void main(String[] args) {CharacterFactory factory = new CharacterFactory();List<Character> document = new ArrayList<>();document.add(factory.getCharacter('H'));document.add(factory.getCharacter('e'));document.add(factory.getCharacter('l'));document.add(factory.getCharacter('l'));document.add(factory.getCharacter('o'));int x = 0;for (Character c : document) {c.display(x++, 0, "black");  // 传递外部状态}}
}

7. 模式变种

  1. 复合享元模式:将多个单纯享元组合成复合对象
  2. 线程级享元:结合ThreadLocal实现线程级共享
  3. 带缓存清理机制:实现LRU缓存策略管理享元对象

8. 优缺点分析

✔️ 优点

  • 极大减少内存中对象的数量
  • 外部状态相对独立,增强程序灵活性
  • 享元对象可被不同场景复用

缺点

  • 增加系统复杂度(需要分离内外状态)
  • 需要额外关注线程安全问题
  • 可能影响程序执行效率(查找/计算外部状态)

9. 相关模式对比

模式目的关键区别
单例模式控制实例数量享元可能有多个不同实例
原型模式对象克隆享元强调共享已有对象
对象池模式重用对象对象池管理临时对象,享元管理永久对象

10. 实际应用案例

  • Java String常量池(-128~127的Integer缓存)
  • 棋牌游戏的棋子对象管理
  • 文档编辑器中的字符/段落格式
  • 图形编辑器中的图形对象
  • 数据库连接池

11. 最佳实践建议

  1. 严格区分内部状态和外部状态
  2. 使用不可变对象作为享元对象
  3. 对享元工厂实现缓存淘汰策略(LRU)
  4. 考虑使用WeakReference管理享元池
  5. 外部状态参数尽量使用基本类型或不可变对象
  6. 多线程环境下需要同步处理享元工厂

🧩 记忆技巧:把享元模式想象成"共享单车"系统,单车(内部状态)是共享的,用户(外部状态)各自的使用位置不同。


http://www.ppmy.cn/devtools/163635.html

相关文章

Spring 集成 MyBatis 操作指南(详细实例)

📝 1. 前言 Spring 框架与 MyBatis 是 Java 开发中常见的组合,MyBatis 作为一款轻量级 ORM 框架,提供灵活的 SQL 语句管理,同时结合 Spring 的依赖注入和事务管理,能大大提高数据库访问的开发效率。本文将详细介绍 Spring 集成 MyBatis 的操作步骤,并提供完整实例。 �…

k8s出问题后 应该查看哪些内容

要确认 Kubernetes (k8s) 系统是否正常运行&#xff0c;需要检查集群的 核心组件、节点状态、Pod 运行情况 和 网络通信。以下是详细步骤和命令&#xff1a; 1. 检查集群节点状态 kubectl get nodes期望输出&#xff1a;所有节点状态为 Ready。异常情况&#xff1a; NotReady&…

使用Docker Compose部署 MySQL8

MySQL 8 是一个功能强大的关系型数据库管理系统,而 Docker 则是一个流行的容器化平台。结合使用它们可以极大地简化 MySQL 8 的部署过程,并且确保开发环境和生产环境的一致性。 安装 Docker 和 Docker Compose 首先,确保你的机器上已经安装了 Docker 和 Docker Compose。 …

Deepseek的缺陷

Deepseek什么都略懂&#xff0c;但答案很难让人满意。 内容蜻蜓点水&#xff0c;什么都有点&#xff0c;但浅薄的很。让玩家很无语。 一些软件类的答案貌似比较详细&#xff0c;但距离能用还差很远。 ----------------- 一些问题的答案如下&#xff1a; 《b4》是一款经典的生…

Spring报错解决一览

Spring错误持续更新贴… 问题一 springcloud-OAuth2.0配置的时候报错 Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a bean of type ‘org.springframework.boot.autoconfigu…

RabbitMQ 高级配置与优化:从入门到精通

RabbitMQ 高级配置与优化:从入门到精通 引言 在分布式架构中,消息队列(MQ)是必不可少的一环,而 RabbitMQ 作为业界广泛使用的消息中间件,凭借其高吞吐、可扩展、可靠性等特性备受青睐。然而,很多开发者和运维人员在使用 RabbitMQ 时,仅仅停留在"能用"的层面…

DDD 架构之领域驱动设计【通俗易懂】

文章目录 1. 前言2. MVC 对比 DDD3. DDD 分层架构4. 完整业务流程 1. 前言 官方回答&#xff1a;DDD是一种应对复杂业务系统的设计方法&#xff0c;通过将软件设计与业务领域紧密结合&#xff0c;帮助开发人员构建清晰、可维护的领域模型。在复杂的业务系统中&#xff0c;它能…

c++中迭代器和指针有什么区别?

在 C 中&#xff0c;迭代器和指针虽然在某些场景下有相似的行为&#xff0c;但它们在设计目的、功能和使用场景上有本质区别。以下是详细对比和最佳实践&#xff1a; 一、核心区别对比表 特征指针迭代器本质原生数据类型&#xff0c;直接存储内存地址类对象&#xff0c;抽象容…