1. 基础概念
享元模式是一种结构型设计模式,在享元模式中,对象被设计为可共享的,可以被多个上下文使用,而不必在每个上下文中都创建新的对象。
想要了解享元模式,就必须要区分什么是内部状态,什么是外部状态。
- 内部状态是指那些可以被多个对象共享的状态,它存储在享元对象内部,并且对于所有享元对象都是相同的,这部分状态通常是不变的。
- 而外部状态是享元对象依赖的、可能变化的部分。这部分状态不存储在享元对象内部,而是在使用享元对象时通过参数传递给对象。
举个例子,图书馆中有很多相同的书籍,但每本书都可以被多个人借阅,图书馆里的书就是内部状态,人就是外部状态。
再举个开发中的例子,假设我们在构建一个简单的图形编辑器,用户可以在画布上绘制不同类型的图形,而图形就是所有图形对象的内部状态(不变的),而图形的坐标位置就是图形对象的外部状态(变化的)。
如果图形编辑器中有成千上万的图形对象,每个图形对象都独立创建并存储其内部状态,那么系统的内存占用可能会很大,在这种情况下,享元模式共享相同类型的图形对象,每种类型的图形对象只需创建一个共享实例,然后通过设置不同的坐标位置个性化每个对象,通过共享相同的内部状态,降低了对象的创建和内存占用成本。
2. 基本结构
享元模式包括以下几个重要角色:
- 享元接口
Flyweight
: 所有具体享元类的共享接口,通常包含对外部状态的操作。 - 具体享元类
ConcreteFlyweight
: 继承Flyweight
类或实现享元接口,包含内部状态。 - 享元工厂类
FlyweightFactory
: 创建并管理享元对象,当用户请求时,提供已创建的实例或者创建一个。 - 客户端
Client
: 维护外部状态,在使用享元对象时,将外部状态传递给享元对象。
3. 简易实现
享元模式的实现通常涉及以下步骤:
- 定义享元接口,接受外部状态作为参数并进行处理。
1 | // 步骤 1: 定义享元接口 |
- 实现具体享元类, 存储内部状态。
1 | // 步骤 2: 实现具体享元类 |
- 创建享元工厂类,创建并管理
Flyweight
对象,当用户请求一个Flyweight
时,享元工厂会提供一个已经创建的实例或者创建一个。
1 | class FlyweightFactory { |
- 客户端使用享元模式
1 | public class Main { |
4. 使用场景
使用享元模式的关键在于包含大量相似对象,并且这些对象的内部状态可以共享。具体的应用场景包括文本编辑器,图形编辑器,游戏中的角色创建,这些对象的内部状态比较固定(外观,技能,形状),但是外部状态变化比较大时,可以使用。