一、概述
享元模式以共享的方式高效地支持大量细粒度对象的重用,享元对象能做到共享的关键时区分了内部状态和外部状态。内部状态时存储在享元对象内部并且不会随环境改变而改变的状态,内部状态可以共享;外部状态时随环境改变而改变的、不可以共享的状态。
具有相同内部状态的对象存储在享元池中,享元池中的对象是可以实现共享的,需要的时候就将对象从享元池中取出,实现对象的复用。
享元模式的定义为:运用共享技术有效地支持大量细粒度对象的复用。系统只是用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此又称为轻量级模式,它是一种对象结构型模式。
享元模式的结构图如下图所示:

二、示例代码
享元模式包括抽象享元类(Flyweight)、具体享元类(ConcreteFlyweight)、非共享具体享元类(UnsharedConcreteFlyweight)以及享元工厂类(FlyweightFactory)。
享元工厂类(FlyweightFactory)的作用在于提供一个用于存储享元对象的享元池,当用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象,享元工厂类的典型代码如下:
1 | public class FlyweightFactory{ |
享元类(Flyweight)要将内部状态和外部状态分开,将内部状态作为享元类的成员变量,外部状态通过注入的方式添加到享元类中,其典型代码如下:
1 | public class Flyweight { |
享元模式与其他模式的联用:
- 在享元模式的享元工厂类中通常提供一个静态的工厂方法用于返回享元对象,使用简单工厂模式来生成享元对象。
- 在一个系统中,通常只有唯一一个享元工厂,因此可以使用单例模式进行享元工厂类的设计。
- 享元模式可以结合组合模式形成复合享元模式,统一对多个享元对象设置外部状态。
Java String类这种在修改享元对象时,先将原有对象复制一份,然后在新对象上再实施修改操作的机制称为“Copy On Write”,
三、demo
网络设备有交换机、集线器这两种类型的设备,同时能够连接到不同的端口。
享元工厂(FlyweightFactory)代码设计如下:
1 | public class DeviceFactory { |
享元类(Flyweight)代码设计如下:
1 | public interface NetworkDevice { |
具体享元类(ConcreteFlyweight)代码设计如下:
1 | public class Switch implements NetworkDevice{ |
1 | public class Hub implements NetworkDevice{ |
非共享具体享元类(UnsharedConcreteFlyweight)
1 | public class Port { |
客户端调用代码如下:
1 | public static void main(String args[]) { |
代码运行结果如下:

四、总结
1. 优点
- 可以极大减少内存中对象的数量,使得相同或相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能。
- 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。
2. 缺点
- 享元模式使得系统变得复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
- 为了使对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态将使得运行时间变长。
3. 适用场景
- 一个系统有大量相同或者相似的对象,造成内存的大量耗费。
- 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
- 在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式。