ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
>[success] # 前端角度思考享元模式 ~~~ 1.书中给出一个场景,有一个服装场,生产50件男士衣服和50件女士衣服,现在为了 推销产品需要拍照做广告,站在极端情况下50个男模特和50个女模特都需要穿衣服来 拍照 ~~~ >[danger] ##### 转成代码 ~~~ // 创建一个模特 性别 和穿的衣服两个属性 var Model = function (sex, clothes) { this.sex = sex this. clothes = clothes } Model.prototype.takePhoto = function () { console.log('sex='+this.sex + ' clothes=' + this. clothes) } // 创建五十个男模特穿衣服 for(var i=1;i<=50;i++){ var maleModel = new Model('male','clothes' + i) // 拍照 maleModel.takePhoto() } // 创建五十个女模特穿衣服 for(var i=1;i<=50;i++){ var maleModel = new Model('female','clothes' + i) // 拍照 maleModel.takePhoto() } ~~~ >[danger] ##### 现在的问题 ~~~ 1.如果后续工厂扩张衣服生产越来越多,那是否就会产生一个问题需要创建的模特对象 也会越来越多,随着对象增多,内存的占越来越多就会出现程序崩溃的问题 ~~~ >[danger] ##### 解决方法 ~~~ 1.只创建一个男模一个女模,他俩去穿这不同款式的衣服去拍照 2.下面的代码只是分别创建了男女模特两个对象,也实现了100件衣服的拍照功能 ~~~ ~~~ // 创建一个模特 性别 和穿的衣服两个属性 var Model = function (sex) { this.sex = sex } Model.prototype.takePhoto = function () { console.log('sex='+this.sex + ' clothes=' + this. clothes) } // 创建一个男模 var maleModel = new Model('male') // 创建一个女模 var femaleModel = new Model('female') // 男模特穿衣服拍照 for(var i=1;i<=50;i++){ maleModel.clothes = 'clothes'+i maleModel.takePhoto() } // 女模特 for(var i=1;i<=50;i++){ femaleModel.clothes = 'clothes'+i femaleModel.takePhoto() } ~~~ >[success] # 享元的概念 >[danger] ##### 书中解释概括 ~~~ 1.享元模式要求将'对象的属性'划分为'内部状态'与'外部状态'(状态在这里通常指属性) 2.享元模式的目标是尽量减少共享对象的数量 3.划分内部状态和外部状态方法(书中给了四条建议): 3.1.内部状态存储于对象内部。 3.2.内部状态可以被一些对象共享。 3.3.内部状态独立于具体的场景,通常不会改变。 3.4.外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享。 4.把所有内部状态相同的对象都指定为同一个共享的对象。而外部状态 可以从对象身 上剥离出来,并储存在外部。 5.通过时间换空间的思路:剥离了外部状态的对象成为共享对象,外部状态在必要时被传 入共享对象来组装成一个完整的对象,外部状态成为一个完整对象的过程需要花费一定的 时间,但却可以大大减少系统中的对象数量,相比之下,这点时间或许是微不足道的。因此 ,享元模式是一种用'时间换空间'的优化模式。 ~~~ >[danger] ##### 根据解释再对案例分析带入 ~~~ 1.性别是'内部状态',衣服是'外部状态',通过区分两种状态,减少了'系统中的对象数量'。 2.'对象的个数由内部对象组合数决定',内部状态有多少种组合,系统中便最多存在多少 个对象,因为性别 通常只有男女两种,所以该内衣厂商最多只需要 2 个对象。 3.'内部对象':可以被对象共享的属性通常被划分为内部状态,如同不管什么样式的衣服, 都可以按照性别不同,穿在同一个男模特或者女模特身上,模特的性别就可以作为内部状 态储存在共享对象的内部。 4.'外部对象':取决于具体的场景,并根据场景而变化,就像例子中每件衣服都是不同的, 它们不能被一些对象共享,因此只能被划分为外部状态。 ~~~ >[danger] ##### 其他文章的总结 * 参考了文章 [私塾国际学府·技术团队](http://techblog.sishuxuefu.com/atricle.html?5bcf34ef808ca40072a6fec2) ~~~ 1.运用共享技术有效地支持大量细粒度的对象。 2.缓存的是对象的实例,实例存放的是属性,如果这些属性不断改变,那么缓存中的数据也 必须跟着改变,那缓存就没有意义了,正是如此也可以理解要把'不变的属性作为内部属性', '改变的部分作为外部状态对外暴露,让外界去改变成为外部属性' ~~~ >[danger] ##### 创建享元需要的具体实现思路 ~~~ 1.书中对之前的衣服代码进行的'分析': 1.1.通过构造函数显式 new 出了男女两个 model 对象,在其他系统中,也许并不是一开始 就需要所有的共享对象。 1.2.给 model 对象手动设置了 clothes外部状态,在更复杂的系统中,这不是一个最好的方 式,因为外部状态可能会相当复杂,它们与共享对象的联系会变得困难。 2.'解决方案': 2.1.通过一个对象工厂来解决第一个问题,只有当某种共享对象被真正需要时,它才从工厂 中被创建出来。 2.2.第二个问题,可以用一个管理器来记录对象相关的外部状态,使这些外部状 态通过某个钩子和共享对象联系起来。 ~~~