Use sharing to support large numbers of fine-grained objects efficiently.
享元模式(Flyweight Pattern):使用共享对象可有效地支持大量的细粒度的对象,从而节省内存。
com.demo.design.pattern.structural.flyweight.Circle
@Data public class Circle { private int radius; private Font font; public void draw() { System.out.println("Circle: [Font : " + font + ", radius : " + radius + "]"); } }
调用示例
@Test public void flyWeightPattern(){ // 事先定义好需要的Circle对象的共享属性 Map<Integer, Font> fontMap = new HashMap<>(10); fontMap.put(1, new Font("Arial Bold", Font.PLAIN, 1)); fontMap.put(2, new Font("Arial Bold", Font.BOLD, 2)); List<Circle> circles = new ArrayList<>(100000); Circle circle; for (int i = 0; i < 100000; ++i) { circle = new Circle(); // 需要大量Circle对象时,共享属性属性可以引用同一个对象 circle.setFont(fontMap.get(i & 1)); // 非共享属性则每个Circle独有 circle.setRadius(new Random().nextInt(100)); circles.add(circle); } circles.forEach(Circle::draw); }
java.lang.Integer
public final class Integer extends Number implements Comparable<Integer> { /** * Returns an {@code Integer} instance representing the specified * {@code int} value. If a new {@code Integer} instance is not * required, this method should generally be used in preference to * the constructor {@link #Integer(int)}, as this method is likely * to yield significantly better space and time performance by * caching frequently requested values. * * This method will always cache values in the range -128 to 127, * inclusive, and may cache other values outside of this range. * * @param i an {@code int} value. * @return an {@code Integer} instance representing {@code i}. * @since 1.5 */ public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } }
Integer缓存对象缓存了 -128 到 127 之间的整型值,这是最常用的一部分整型值,JDK也提供了方法来自定义缓存的最大值。
java.lang.Integer.IntegerCache
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }
减少应用程序创建的对象, 降低程序内存的占用, 增强程序的性能。
提高了系统复杂性, 需要分离出外部状态和内部状态, 而且外部状态具有固化特性, 不应该随内部状态改变而改变, 否则导致系统的逻辑混乱。
系统中存在大量的相似对象。
细粒度的对象都具备较接近的外部状态, 而且内部状态与环境无关, 也就是说对象没有特定身份。
需要缓冲池的场景。