Javascript 设计模式 - 享元模式

839 阅读3分钟

享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。

享元模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

适应场景

解决的问题: 在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

使用注意: 使用了享元模式之后,我们需要分别多维护一个 factory 对象和一个 manager 对象,在大部分不必要使用享元模式的环境下,这些开销是可以避免的。

因此我们可以在以下场景中使用享元模式:

  • 一个程序中使用了大量的相似对象。
  • 由于使用了大量对象,造成很大的内存开销。
  • 对象的大多数状态都可以变为外部状态。
  • 剥离出对象的外部状态之后,可以用相对较少的共享对象取代大量对象。

内部状态与外部状态

享元模式要求将对象的属性划分为内部状态外部状态(状态在这里通常指属性)。享元模式的目标是尽量减少共享对象的数量,那么如何划分内部状态和外部状态呢?

  • 内部状态存储于对象内部。
  • 内部状态可以被一些对象共享。
  • 内部状态独立于具体的场景,通常不会改变。
  • 外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享。

把所有内部状态相同的对象都指定为同一个共享的对象。而外部状态 可以从对象身上剥离出来,并储存在外部。

剥离了外部状态的对象成为共享对象,外部状态在必要时被传入共享对象来组装成一个完整 的对象。虽然组装外部状态成为一个完整对象的过程需要花费一定的时间,但却可以大大减少系 统中的对象数量,相比之下,这点时间或许是微不足道的。因此,享元模式是一种用时间换空间的优化模式。

使用享元模式的关键是如何区别内部状态外部状态

举例

  • 代码关键点:用 HashMap 对象池存储这些对象。
// 享元模式,对象池缓存对象
class colorFactory {
  constructor(name) {
    this.colors = {};
  }
  create(name) {
    let color = this.colors[name];
    if (color) return color;
    this.colors[name] = new Color(name);
    return this.colors[name];
  }
};

优缺点

优点: 大大减少对象的创建,降低系统的内存,使效率提高。

缺点: 提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

参考