设计模式实战:享元模式(Flyweight)

在很多系统中,会存在这样的情况:

  • 对象数量非常多
  • 对象之间大量属性是相同的
  • 只有少量状态不同

如果每个对象都完整创建,就会导致:

  • 内存占用巨大
  • 对象创建成本高
  • 系统性能下降

这时候就可以使用 享元模式(Flyweight)


一、享元模式解决什么问题?

一句话:

通过共享对象,减少内存使用。

核心思想:

  • 把对象中可共享的部分提取出来
  • 多个对象共享同一份数据
  • 只把不同的部分作为外部状态

关键词:

  • 对象共享
  • 内存优化
  • 内部状态
  • 外部状态

二、一个典型场景:文本编辑器

假设一个文档有 100万字符

每个字符对象可能包含:

  • 字符内容
  • 字体
  • 字号
  • 颜色
  • 位置

如果每个字符都是完整对象:

复制代码
1000000 × 字体信息 × 样式信息

大量数据是重复的。

例如:

复制代码
字符: "A"
字体: Arial
字号: 12
颜色: 黑

可能出现几十万次。

这就是典型的享元模式使用场景。


三、享元模式的核心思想

享元模式会把对象状态拆成两部分:

1️⃣ 内部状态(Internal State)

可共享、不会变化。

例如:

  • 字符内容
  • 字体
  • 字号
  • 样式

这些可以被多个对象共享。


2️⃣ 外部状态(External State)

不可共享,每次不同。

例如:

  • 文档位置
  • 行号
  • 列号

这些由外部传入。


四、享元模式结构

典型结构:

复制代码
Flyweight
   |
ConcreteFlyweight
   |
FlyweightFactory

关键组件:

  • Flyweight:共享对象接口
  • ConcreteFlyweight:具体享元对象
  • FlyweightFactory:享元工厂(负责缓存)

五、Python 实现示例

我们实现一个"字符享元"。


1️⃣ 享元对象

python 复制代码
class CharacterFlyweight:

    def __init__(self, char, font, size):
        self.char = char
        self.font = font
        self.size = size

    def render(self, position):
        print(f"{self.char} ({self.font}, {self.size}) at {position}")

注意:

  • char/font/size → 内部状态
  • position → 外部状态

2️⃣ 享元工厂

python 复制代码
class FlyweightFactory:

    def __init__(self):
        self._cache = {}

    def get_character(self, char, font, size):
        key = (char, font, size)

        if key not in self._cache:
            self._cache[key] = CharacterFlyweight(char, font, size)

        return self._cache[key]

这里就是核心:

相同对象只创建一次。


3️⃣ 使用方式

python 复制代码
factory = FlyweightFactory()

c1 = factory.get_character("A", "Arial", 12)
c2 = factory.get_character("A", "Arial", 12)

c1.render(10)
c2.render(20)

注意:

复制代码
c1 is c2

这两个对象是 同一个实例


六、享元模式的关键:对象缓存

享元模式本质上是:

对象缓存 + 对象共享

最常见实现方式:

  • 字典缓存
  • 对象池
  • 单例对象集合

七、Python 中的"天然享元"

Python 其实已经在很多地方使用享元思想。

例如:

小整数缓存

python 复制代码
a = 10
b = 10

print(a is b)

结果:

复制代码
True

因为 Python 会缓存 -5 到 256 的整数


字符串驻留(String Interning)

python 复制代码
a = "hello"
b = "hello"

print(a is b)

很多情况下也是同一个对象。

这其实就是享元思想。


八、真实项目中的应用

享元模式非常适合:

1️⃣ 游戏开发

大量:

  • 子弹
  • 粒子
  • 树木
  • 草地

模型数据可以共享。


2️⃣ UI 系统

大量:

  • 图标
  • 字体
  • 样式

3️⃣ 缓存系统

例如:

  • 配置对象
  • 模板对象
  • 常用数据

4️⃣ ORM 框架

数据库字段、表结构元数据通常会共享。


九、享元模式优缺点

✅ 优点

  • 大幅减少内存使用
  • 减少对象创建成本
  • 提升系统性能

❌ 缺点

  • 系统结构变复杂
  • 外部状态管理困难
  • 不适合状态复杂对象

十、什么时候使用享元模式?

适合:

  • 大量对象
  • 对象大部分状态相同
  • 系统内存压力大

不适合:

  • 对象差异很大
  • 状态复杂
  • 对象数量不多

经验法则:

当对象数量达到几十万甚至百万级时,才值得考虑享元模式。


十一、一句话总结

享元模式的本质是:
共享不变数据,分离变化数据。

用一句更直白的话:

不要重复创建相同对象。

相关推荐
AI人工智能+电脑小能手4 小时前
大白话说Java设计模式-46-责任链模式(业务实战篇)
java·设计模式·责任链模式·风控校验·servlet filter·spring interceptor·链式处理
lupai6 小时前
手机在网状态接口实测效果与质量评估
大数据·python·智能手机·api接口
荷蒲7 小时前
【小白量化Qbuddy】用AI设计miniQMT指标公式计算量化平台
人工智能·python·机器人
阿童木写作7 小时前
跨境电商图片翻译工具,批量翻译视频字幕一键抠图
人工智能·python·音视频
何以解忧,唯有..8 小时前
Pydantic 介绍与使用:Python 数据校验的现代方案
数据库·python·microsoft
又幸福了哥9 小时前
Python入门到高级(知识点七)
python
又幸福了哥9 小时前
Python入门到高级(知识点六)
python
维克兜率天9 小时前
【维克】动量指标家族:RSI、ROC、CCI、Momentum全面解析
python·算法
XZ-07000110 小时前
week2-1-可视化
开发语言·python
Java后端的Ai之路10 小时前
14、Python - 责任链模式
服务器·开发语言·人工智能·python·责任链模式