设计模式 享元模式
本文将介绍设计模式中的享元模式。
一、什么是享元模式?
如果一个软件系统在运行时所创建的相同或相似对象数量太多,将导致运行代价过高,带来系统资源浪费、性能下降等问题。享元模式正是用于解决这一问题的,它通过共享技术实现相同或相似对象的复用。
享元模式,运用共享技术有效地支持大量细粒度对象的复用。
二、享元池
在享元模式中,存储共享实例对象的地方被称为享元池。
三、内部状态和外部状态
要实现相同对象的复用非常简单,只需要将对象存入享元池,需要时取出即可。
要做到相似对象的复用,首先便要对这些对象的相同部分和相似部分做抽象,在享元模式中,抽象为内部状态和外部状态,具体如下:
- 内部状态:
- 存储在享元对象内部
- 不会随环境改变而改变
- 可共享
- 简单来说,内部状态就是相同部分
- 外部状态:
- 通常由调用者保存,在享元对象需要使用时再传入
- 随环境改变而改变
- 不可共享
- 简单来说,外部状态就是相似部分
通过内部状态和外部状态的区分,可以实现相似对象的复用。
四、实现
1. 结构
2. 角色
- Flyweight 抽象享元类:
- 通常是接口或抽象类
- 声明了具体享元类公共的方法,包括:
- 获取内部状态
- 设置外部状态
- ConcreteFlyweight 具体享元类:
- 实现了 Flyweight 抽象享元类
- 通常结合单例模式,使得每一个 ConcreteFlyweight 具体享元类都只有一个唯一的实例化对象
- UnsharedConcreteFlyweight 非共享具体享元类:
- 并不是所有 Flyweight 抽象享元类的子类都需要被共享,不能被共享的子类可以设计为 UnsharedConcreteFlyweight 非共享具体享元类
- 当需要 UnsharedConcreteFlyweight 非共享具体享元类的实例化对象时,直接通过实例化创建
- FlyweightFactory 享元工厂类:
- 用于创建和管理享元对象
- 它针对抽象享元类编程
- 将各种类型的具体享元对象存储在一个享元池中
- 当用户请求一个具体享元对象时,
- 如果享元池中已存储有实例,则直接返回
- 否则,创建实例,放入享元池,返回
3. 简单示例
Flyweight:
1 |
|
ConcreteFlyweight:
1 |
|
UnsharedConcreteFlyweight:
1 |
|
FlyweightFactory:
1 |
|
五、享元模式与 String
JDK 类库中的 String 类使用了享元模式。
六、优缺点
1. 优点
- 可以减少内存占用,节省系统资源
2. 缺点
- 使系统变得更复杂
- 为实现相似对象的复用,需要抽象内部状态和外部状态
参考
- 《Java 设计模式》