意图
利用共享的方式来支持大量细粒度的对象,这些对象一部分内部状态是相同的。它让某个类的一个实例能用来提供许多”虚拟实例”。
类图
- 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字符串常量池
系列导航
- 上一篇:外观(Facade)
- 下一篇:代理(Proxy)
- 结构型模式接近尾声,相关阅读:适配器 · 装饰