一、是什么
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式
也就是说如果系统中存在多个相同的对象,那么只需共享一份就可以了,不必每个都去实例化每一个对象,这样来精简内存资源,提升性能和效率
二、使用
假设有个衣服工厂,目前的产品有50种男士衣服和50种女士衣服,为了推销产品,工厂决定生产一些塑料模特来穿上衣服拍成广告照片。正常情况下需要50个男模特和50个女模特,然后分别让他们每人分别穿上一件衣服来拍照
不使用享元模式的情况下,代码如下:
var Model = function (sex, cloth) {
this.sex = sex; this.cloth = cloth;
};
Model.prototype.takePhoto = function () {
console.log('sex= ' + this.sex + ' cloth=' + this.cloth);
};
for (var i = 1; i <= 50; i++) {
var maleModel = new Model('male', 'cloth' + i);
maleModel.takePhoto();
};
for (var j = 1; j <= 50; j++) {
var femaleModel = new Model('female', 'cloth' + j);
femaleModel.takePhoto();
};
虽然实现了这个需求,想必也一定创建了100个模特对象。想象一下如果衣服种类无休止的增长下去,那么模特对象的数量也会增长下去,当对象多到一定数量程序必然会崩溃
可以通过享元模式进行优化,而使用享元模式的核心就是学会划分内部状态和外部状态,对应特征如下:
内部状态存储于对象的内部
内部状态可以被一些对象共享
内部状态独立于具体的场景,通常不会改变
外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享
构建享元对象
class Modal {
constructor(id, gender) {
this.gender = gender
this.name = `张${gender}${id}`
}
}
构建享元工厂
class ModalFactory {
//单例模式
static create(id, gender) {
if (this[gender]) {
return this[gender]
}
return this[gender] = new Modal(id, gender)
}
}
管理外部状态
class TakeClothesManager {
// 添加衣服款式
static addClothes(id, gender, clothes) {
const modal = ModalFactory.create(id, gender)
this[id] = {
clothes,
modal
}
}
// 拍照
static takePhoto(id) {
const obj = this[id]
console.log(`${obj.modal.gender}模特${obj.modal.name}穿${obj.clothes}拍了张照`)
}
}
执行
for (let i = 0; i < 50; i++) {
TakeClothesManager.addClothes(i, '男', `服装${i}`)
TakeClothesManager.takePhoto(i)
}
for (let i = 50; i < 100; i++) {
const {addClothes, takePhoto} = TakeClothesManager
TakeClothesManager.addClothes(i, '女', `服装${i}`)
TakeClothesManager.takePhoto(i)
}
三、应用场景
享元模式是一种很好的性能优化方案,但它也会带来一些复杂性的问题,一般来说,以下情况发生时便可以使用享元模式。
对象的大多数状态都可以变为外部状态
一个程序中使用了大量的相似对象
由于使用了大量对象,造成很大的内存开销
剥离出对象的外部状态之后,可以用相对较少的共享对象取代大量对象
例如对象池维护一个装载空闲对象的池子,如果需要对象的时候,不是直接 new
。而是转从对象池里获取。如果对象池里没有空闲对象,则创建一个新的对象,当或取出的对象完成它的职责之后,再进入池子等待下次被获取
对象池技术的应用非常广泛,HTTP连接池和数据库连接池都是其代表应用。在 Web 前端开发中,对象池使用最多的场景是跟DOM相关的操作。很多空间和时间都消耗在了 DOM 节点上,要学会如何避免频繁地创建和删除DOM节点
参考文献
https://www.runoob.com/design-pattern/flyweight-pattern.html
https://zhuanlan.zhihu.com/p/79819642
https://juejin.cn/post/6998395419214479397
https://segmentfault.com/a/1190000013366000
--The End--
系列正在更新:11/14
点击下方卡片解锁更多
创作不易,星标、点赞、在看 三连支持