
设计模式-享元模式
设计模式之享元模式
1. 概述
享元模式 是一种结构型设计模式,它通过共享细粒度的对象来有效地支持大量对象。 享元模式尝试重用现有对象,而不是创建新的对象。通过共享,享元模式可以减少内存使用,提高性能。
2. 模式意图
- 减少对象数量: 通过共享对象来减少应用程序中的对象数量,从而减少内存占用。
- 提高性能: 通过重用现有对象来避免创建新对象的开销,从而提高性能。
- 分离内部状态和外部状态: 将对象的状态分为内部状态(可以共享)和外部状态(需要在使用时传入),从而使对象可以被共享。
3. 模式结构
享元模式主要包含以下角色:
- 享元接口 (Flyweight):
- 定义了享元对象需要实现的接口。
- 通常包含一个或多个方法,用于操作享元对象的外部状态。
- 具体享元 (Concrete Flyweight):
- 实现了享元接口。
- 存储享元对象的内部状态。
- 是可共享的对象。
- 非共享具体享元 (Unshared Concrete Flyweight): (可选)
- 实现了享元接口。
- 存储享元对象的内部状态。
- 不可共享的对象。
- 享元工厂 (Flyweight Factory):
- 负责创建和管理享元对象。
- 维护一个享元池(例如,一个 Map),用于存储已经创建的享元对象。
- 当客户端请求一个享元对象时,工厂首先检查享元池中是否已经存在该对象。 如果存在,则直接返回该对象;否则,创建一个新的对象并将其添加到享元池中。
- 客户端 (Client):
- 通过享元工厂来获取享元对象。
- 负责传递享元对象的外部状态。
4. 适用场景
- 应用程序中使用大量的对象。
- 大量对象拥有相同的内部状态,可以将内部状态共享。
- 对象的外部状态可以与内部状态分离。
- 通过共享对象可以显著减少内存占用。
5. 优缺点
优点:
- 减少内存占用: 通过共享对象来减少应用程序中的对象数量,从而减少内存占用。
- 提高性能: 通过重用现有对象来避免创建新对象的开销,从而提高性能。
缺点:
- 增加了系统的复杂性: 需要分离内部状态和外部状态,并创建享元工厂来管理享元对象,增加了系统的复杂性。
- 读取享元状态的开销: 如果外部状态需要频繁地传递给享元对象,可能会导致额外的性能开销。
- 线程安全问题: 需要考虑多线程环境下享元对象的线程安全问题。
6. 代码示例
场景:
假设你正在开发一个文本编辑器。 在文本编辑器中,可能会有很多重复的字符,例如,字母 “a”、数字 “1” 等。 如果为每个字符都创建一个对象,会占用大量的内存。 使用享元模式,你可以将这些重复的字符对象共享,从而减少内存的占用。
1. 享元接口 (Flyweight Interface)
1 | // 享元接口,定义了字符的通用操作 |
2. 具体享元 (Concrete Flyweight)
1 | // 具体享元,表示具体的字符 |
3. 享元工厂 (Flyweight Factory)
1 | // 享元工厂,用于创建和管理享元对象 |
4. 客户端 (Client)
1 | // 客户端 |
7. 关键点说明:
CharacterFlyweight接口: 定义了display()方法,表示字符的通用操作。 这就是**享元接口 (Flyweight Interface)**。ConcreteCharacter类: 实现了CharacterFlyweight接口,表示具体的字符。 它包含一个character字段,用于存储字符的值。 这就是**具体享元 (Concrete Flyweight)**。CharacterFactory类: 用于创建和管理享元对象。 它维护一个characterMap,用于存储已经创建的字符对象。 当客户端请求一个字符对象时,工厂首先检查characterMap中是否已经存在该对象。 如果存在,则直接返回该对象;否则,创建一个新的对象并将其添加到characterMap中。 这就是**享元工厂 (Flyweight Factory)**。FlyweightPatternDemo类: 客户端代码,演示了如何使用享元模式来共享字符对象。
8. 运行结果:
1 | 创建字符: A |
9. 总结
享元模式 通过共享细粒度的对象,从而减少内存的占用。 享元模式适用于当应用程序中存在大量的重复对象,并且这些对象的状态可以分离成内部状态和外部状态时。 内部状态可以被共享,而外部状态需要在每次使用对象时传入。 合理使用享元模式可以减少内存占用,提高应用程序的性能。
本文是原创文章,采用CC BY-NC-SA 4.0协议,完整转载请注明来自徍正的随笔Blog








