CHARLIE SAYS

查理如是说
DATE 2026-08-24
THEME
SERIES / DESIGN_PATTERNS / P-108 · 设计模式

设计模式 014:享元(Flyweight)

意图

利用共享的方式来支持大量细粒度的对象,这些对象一部分内部状态是相同的。它让某个类的一个实例能用来提供许多”虚拟实例”。

类图

  • Flyweight:享元对象
  • IntrinsicState:内部状态,享元对象共享内部状态
  • ExtrinsicState:外部状态,每个享元对象的外部状态不同
classDiagram
    class Flyweight {
        <<interface>>
        +doOperation(extrinsicState String) void
    }
    class ConcreteFlyweight {
        -intrinsicState String
        +doOperation(extrinsicState String) void
    }
    class FlyweightFactory {
        -flyweights HashMap~String,Flyweight~
        +getFlyweight(intrinsicState String) Flyweight
    }
    class Client
    Flyweight <|.. ConcreteFlyweight
    FlyweightFactory o-- Flyweight : 缓存共享
    Client ..> FlyweightFactory

关键在 FlyweightFactory:相同内部状态的对象只在第一次创建,之后全部复用同一个实例。

实现

public interface Flyweight {
    void doOperation(String extrinsicState);
}

public class ConcreteFlyweight implements Flyweight {
    private String intrinsicState;

    public ConcreteFlyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }

    @Override
    public void doOperation(String extrinsicState) {
        System.out.println("Object address: " + System.identityHashCode(this));
        System.out.println("IntrinsicState: " + intrinsicState);
        System.out.println("ExtrinsicState: " + extrinsicState);
    }
}
public class FlyweightFactory {
    private HashMap<String, Flyweight> flyweights = new HashMap<>();

    Flyweight getFlyweight(String intrinsicState) {
        if (!flyweights.containsKey(intrinsicState)) {
            Flyweight flyweight = new ConcreteFlyweight(intrinsicState);
            flyweights.put(intrinsicState, flyweight);
        }
        return flyweights.get(intrinsicState);
    }
}
public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight flyweight1 = factory.getFlyweight("aa");
        Flyweight flyweight2 = factory.getFlyweight("aa");
        flyweight1.doOperation("x");
        flyweight2.doOperation("y");
    }
}

输出——注意两次获取的对象地址相同(同一实例复用),但外部状态不同:

Object address: 1163157884
IntrinsicState: aa
ExtrinsicState: x
Object address: 1163157884
IntrinsicState: aa
ExtrinsicState: y

JDK 中的应用

Java 利用缓存来加速大量小对象的访问时间,这就是享元模式:

  • java.lang.Integer#valueOf(int)——Integer 缓存池(-128 ~ 127,详见 Java 基础 - 知识点中的常量池分析)
  • java.lang.Boolean#valueOf(boolean)
  • java.lang.Byte#valueOf(byte)
  • java.lang.Character#valueOf(char)
  • String 字符串常量池

系列导航

← Angular 22+ 教程 14:组件查询——@ViewChild / @ContentChild 与信号查询 目录 软件工程 014:开发实践:测试驱动开发(TDD) →
← 返回文章列表