描述
定义
运用共享技术有效地支持大量细粒度的对象。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。又称为轻量级模式。
享元对象能做到共享的关键是区分内部状态(Internal State)和外部状态(External State)。内部状态是存储在享元对象内部的,并且是不会随环境的改变而有所不同。外部状态是随环境的改变而改变的、不可以共享的。享元对象的外部状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。
类型
对象结构型模式
UML类图
实现
- 删除外部状态:该模式的可用性在很大程度上取决于容易识别外部状态并将它从共享对象中删除。
- 管理共享对象:因为对象是共享的,用户不能直接对它进行实例化,因此FlyweightFactory可以帮助用户查找某个特定的Flyweight对象。
主要角色
- Flyweight:享元接口类
- 描述一个接口,通过这个接口flyweight可以接受并作用于外部状态。
- ConcreteFlyweight:享元实现类
- 实现Flyweight接口,并为内部状态增加存储空间。
- 所存储的状态必须是内部的,即它是可共享的,它必须独立于ConcreteFlyweight对象的场景。
- UnsharedConcreteFlyweight:非共享享元实现类(非必需)
- 并非所有的Flyweight子类都需要被共享。
- 在Flyweight对象结构的某些层次,UnshardConcreteFlyweight对象通常将ConcreteFlyweight对象作为子节点。
- FlyweightFactory:享元工厂类
- 创建并管理flyweight对象,确保合理地共享flyweight。
- 当用户请求一个flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。
- Client:客户类
- 维持对flyweight的引用,计算或存储一个(多个)flyweight的外部状态。
代码示例
-
Flyweight:享元接口类
interface Flyweight { void operation(String state); }
-
ConcreteFlyweight:享元实现类
public class ConcreteFlyweight implements Flyweight { private String state; public ConcreteFlyweight(String state) { this.state = state; } @Override public void operation(String state) { System.out.println("内蕴状态:" + this.state); System.out.println("外蕴状态:" + state); } }
-
FlyweightFactory:享元工厂类
public class FlyWeightFactory { private Map<String, ConcreteFlyweight> flyWeights = new HashMap<String, ConcreteFlyweight>(); public ConcreteFlyweight create(String state) { ConcreteFlyweight flyweight = flyWeights.get(state); if(null == flyweight) { flyweight = new ConcreteFlyweight(state); flyWeights.put(state, flyweight); } return flyweight; } }
-
Client:客户类
public class Client { public static void main(String[] args) { FlyWeightFactory factory = new FlyWeightFactory(); Flyweight a = factory.create("a"); Flyweight b = factory.create("b"); Flyweight c = factory.create("a"); f1.operation("a fly weight"); f2.operation("b fly weight"); f3.operation("c fly weight"); System.out.println(f1 == f3); } }
适用场景
- 应用使用了大量相同或者相似的对象。
- 完全由于使用大量的对象,造成很大的内存开销。
- 对象的大多数状态都可变为外部状态。
- 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
- 应用不依赖于对象标识,这些对象是不可分辨的。
优点
- 避免创建大量非常相似对象的开销。
- 极大减少创建对象的数量,以减少内存占用和提高性能。
缺点
- 提高了系统的复杂度,需要分离出内部状态和外部状态。
- 读取外部状态可能会使得运行时间变长。
相关模式
- 通常和Composite模式结合起来,用共享叶结点的有向无环图实现一个逻辑上的层次结构。
- 最好用Flyweight实现State和Strategy对象。
- 通常会使用工厂模式创建一个享元工厂来负责维护一个享元池(Flyweight Pool)用于存储具有相同内部状态的享元对象。