从JDK中学习设计模式——享元模式

这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

概述

享元模式(Flyweight Pattern)通过共享来支持对象的复用,减少资源的浪费。由于享元模式要求被共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式

享元模式的对象有两种状态,分别是内部状态和外部状态。例如:张三开了一家水壶制造厂,一台机器生产一个水壶太奢侈了,因此生产水壶的机器会被共用。生产机器就是内部状态,生产出来的水壶就是外部状态。

  • 内部状态:存储在享元对象内部,不会随环境改变而改变的状态,可以共享

  • 外部状态:对象得以依赖的一个标记,随环境的改变而改变,不可共享

结构

享元模式UML.png

  • FlyweightFactory(享元工厂类):用于创建和管理享元对象,它针对抽象享元类编程,将各种具体享元对象存储在一个享元池中。当用户请求一个具体享元对象时,享元工厂会检査系统中是否存在符合要求的享元对象,如果存在则提供给客户端,如果不存在,就创建一个新的享元对象。

  • Flyweight(抽象享元类):通常是接口或抽象类,它声明了具体享元类的公共方法。通过这些方法可以向外界提供享元对象的内部状态设置外部状态

  • ConcreteFlyweight(具体享元类):它实现了抽象享元类所声明的方法,其实例称为享元对象,为内部状态提供存储空间

  • UnsharedConcreteFlyweight(非共享具体享元类):并不是所有抽象享元类的子类都需要被共享,不需要被共享的外部状态可设计为非共享具体享元类,它以参数的形式注入到具体享元的相关方法中,可以直接实例化

优点

  1. 通过共享对象减少了内存中对象的数量,降低了内存的占用,提高了系统的性能
  2. 享元模式的外部状态相对独立,不会影响其内部状态,从而使享元对象可以在不同的环境中被共享。

缺点

  1. 需要分离出内部状态和外部状态,增加了系统的复杂性
  2. 为了使对象可以共享,需要将部分状态外部化,而读取外部状态会使运行时间变长

应用场景

  1. 系统中存在大量的相似对象。
  2. 细粒度的对象都具备较接近的外部状态,并且内部状态与环境无关。
  3. 需要缓冲池的场景。

JDK 中的应用

JDK 中的 java.lang.String#intern()java.lang.Integer#valueOf() 都使用了享元模式。

public final class Integer extends Number implements Comparable<Integer> {

    private static class IntegerCache {
        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
    }  
}

复制代码

Guess you like

Origin juejin.im/post/7031543219066404878