享元模式

112 阅读2分钟

享元模式

定义

享元:共享的单元的意思。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。

不可变对象,指的是一旦通过构造函数初始化完成之后,它的状态(对象的成员变量或者属性)就不会再被修改了。

所以,不可变对象不能暴露任何 set() 等修改内部状态的方法。

之所以要求享元是不可变对象,那是因为它会被多处代码共享使用,避免一处代码对享元进行了修改,影响到其他使用它的代码。

举个例子,有个服装店,现在男女服装各100套,店家想把这总共200套衣服都穿在模特身上拍照作为展品。我们既可以批量构造对象或就构建男女对象,如下:

// 方式一
let Model = function (gender, style) {
  this.gender = gender
  this.style = style
}
for (let i = 0; i < 100; i++) {
  let maleModel = new Model('male', 'style' + i)
}
for (let i = 0; i < 100; i++) {
  let femaleModel = new Model('female', 'style' + i)
}

// 方式二
let Model = function (gender) {
  this.gender = gender
}
let maleModel = new Model('male')
let femaleModel = new Model('female')
for (let i = 0; i < 100; i++) {
  maleModel.style = 'style' + i
}
for (let i = 0; i < 100; i++) {
  maleModel.style = 'style' + i
}

方式二代码就用到了享元模式,先根据性别来分别构建2种对象,避免不必要的内存损耗。其实在这里性别就是一种内部状态,构建出来的享元对象是不可变对象。变化的仅仅是模特实例传什么样的衣服而已。

适用场景

享元模式可以说是一种很好的性能优化方案,但它也会带来一些复杂性的问题,从上面代码的比较可以看到,享元模式需要分别多维护一个maleModel对象和一个femaleModel对象,在大部分不必要使用享元模式的环境下,这些开销是可以避免的。

享元模式带来的好处很大程度上取决于如何使用以及何时使用,一般来说,以下情况发生时便可以使用享元模式:

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