面试官:说说你对享元模式的理解?应用场景?

7dc77ff3ee9e82e0186e3727fec277fa.png

一、是什么

享元模式(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

点击下方卡片解锁更多

e92b2cf5e82a81cf8a722fa830d21624.png

创作不易,星标、点赞、在看 三连支持

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值