一、享元模式的定义及使用场景

享元模式是为了解决性能问题而诞生的设计模式,这和大部分设计模式为了提高程序复用性的原因不太一样,如果系统中因为创建了大量类似对象而导致内存占用过高,享元模式就非常有用了。

享元模式的关键是区分内部状态和外部状态,剥离了外部状态的对象成为共享对象。有多少种内部状态的组合,系统中便最多存在多少个共享对象。而外部状态存在于共享对象的外部,在必要时被传入共享对象来组成一个完整的对象。一般情况下,以下情况发生时,可以使用享元模式:

1)一个程序使用了大量的类似对象;

2)由于使用了大量对象,造成了很大的内存开销;

3)对象的大部分状态都可以变为外部状态;

剥离出对象的外部状态后,可以用相对较少的共享对象取代大量对象。

二、享元模式使用案例

享元模式中通常存在这样的角色:

1)对象工厂:当共享对象真正被需要时,才从工厂中生产出来;

2)管理器,使用管理器来记录对象相关的外部状态,使得这些外部状态通过某个钩子和共享对象联系起来。

以文件上传为案例进行分析,web上传一般支持多种方式,如浏览器插件,flash和表单上传等。为了简化例子,假设只有插件和Flash两种方式,无论是插件上传,还是Flash上传,原理都一样,当用户选择了文件之后,插件和Flash都会通知调用window下的一个全局Javascript函数,它的名字是startUpload,用户选择的文件列表被组合成一个数组files塞进该函数的参数列表中,代码如下:

    var id=;
window.startUpload=function(uploadType,files){
for(var i=,len=files.length;i<len;i++){
var curFile=files[i];
var uploadObj=new Upload(uploadType,curFile.fileName,curFile.fileSize);
uploadObj.init(id++);
}
};

可见,如果同时选择2000个文件,就会在程序中同时new了2000个upload对象,结果可想而知,浏览器很可能进入假死状态。

对上面的情况使用享元模式进行改造,uploadType作为内部状态,其他外部状态可以剥离出来。

//享元模式学习
var Upload=function(uploadType){
this.uploadType=uploadType;
};
Upload.prototype.delFile=function(id){
uploadManager.setExternalState(id,this);
if(this.fileSize<){
return this.dom.parentNode.removeChild(this.dom);
}
if(window.confirm('确定要删除文件吗'+this.fileName)){
return this.dom.parentNode.removeChild(this.dom);
}
}; //使用对象工厂进行对象实例化,使得只在需要的时候才产生对象
var uploadFactory=(function(){
var uploadPool={};
return {
create:function(uploadType){
if(uploadPool[uploadType]){
return uploadPool[uploadType];
}
return uploadPool[uploadType]=new Upload(uploadType);
},
};
})(); //使用管理器封装外部状态 var uploadManager=(function(){
//保存所有upload对象的外部状态
var uploadDatabase={};
return {
add:function(id,uploadType,fileName,fileSize){
var uploadObj=uploadFactory.create(uploadType);
var dom=document.createElement('div');
dom.innerHTML='文件名称'+fileName+',文件大小'+fileSize+'<button class="delFile">删除</button>';
dom.querySelector('.delFile').onclick=function(){
uploadObj.delFile(id);
}; uploadDatabase[id]={
fileName:fileName,
fileSize:fileSize,
dom:dom
};
return uploadObj;
}, setExternalState:function(id,obj){
var temp=uploadDatabase[id];
for(var key in temp){
obj[key]=temp[key];
}
};
};
})(); //此时触发上传的函数变成
var id=;
window.startUpload=function(uploadType,files){
for(var i=,len=files.length;i<len;i++){
var curFile=files[i];
var uploadObj=uploadManager.add(++id,uploadType,curFile.fileName,curFile.fileSize); }
};

可见,此时,不论上传多少文件,都仅需要创建两个uploadObj对象即可,系统性能得到了较大提升。

三、享元模式的进一步讨论

1)没有内部状态的享元模式

试想,如果系统中只有Flash或者插件一种上传方式,那么产生对象的工厂就变成了单例模式

    //如果没有内部状态,则生产对象的工厂实质上就变成了单例工厂,此时共享对象没有内部状态的区分,不过还是有剥离外部状态的过程,依旧倾向于称之为享元模式
var uploadFactory=(function(){
var uploadObj;
return{
create:function(){
if(uploadObj){
return uploadObj;
}
return uploadObj=new Upload();
}
} })();

2)没有外部对象的享元模式

java,c#中的字符串,对象池(http连接池,数据库连接池)都属于这种情况,在web前端中,对象池使用最多的是dom有关的操作。对象池和享元模式的思想有点像,但因为没有剥离外部对象的过程,一般不称之为享元模式。下面是一个通用的对象池代码实现:

var objectPoolFactory=function(createObjFn){
var objPool=[];
return{
create:function(){
var obj=objPool.length==?createObjFn.apply(this,arguments):objPool.shift();
return obj;
},
recover:function(obj){
objPool.push(obj);
},
};
}

javascript设计模式学习之十二——享元模式的更多相关文章

  1. C#设计模式之十二享元模式(Flyweight)【结构型】

    一.引言   今天我们要讲[结构型]设计模式的第六个模式,该模式是[享元模式],英文名称是:Flyweight Pattern.还是老套路,先从名字上来看看."享元"是不是可以这样 ...

  2. C#设计模式学习笔记:(11)享元模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7792973.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲结构型设计模式的第六个模式--享 ...

  3. Javascript设计模式理论与实战:享元模式

    享元模式不同于一般的设计模式,它主要用来优化程序的性能,它最适合解决大量类似的对象而产生的性能问题.享元模式通过分析应用程序的对象,将其解析为内在数据和外在数据,减少对象的数量,从而提高应用程序的性能 ...

  4. 设计模式学习-使用go实现享元模式

    享元模式 定义 优点 缺点 适用场景 代码实现 享元模式和单例模式的区别 参考 享元模式 定义 享元模式(Flyweight),运用共享技术有效的支持大量细粒度的对象. 享元模式的意图是复用对象,节省 ...

  5. javascript设计模式学习之十五——装饰者模式

    一.装饰者模式定义 装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象.这种为对象动态添加职责的方式就称为装饰者模式.装饰者对象和它所装饰的对象拥有一致的接口,对于用 ...

  6. javascript设计模式学习之十四——中介者模式

    一.中介者模式的定义和应用场景 中介者模式的作用在于解除对象之间的紧耦合关系,增加一个中介者之后,所有对象都通过中介者来通信,而不是互相引用,当一个对象发生变化的时候,仅需要通知中介者即可.从而将网状 ...

  7. 设计模式(十)享元模式Flyweight(结构型)

    设计模式(十)享元模式Flyweight(结构型) 说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释 ...

  8. Java 设计模式系列(十一)享元模式

    Java 设计模式系列(十一)享元模式 Flyweight 享元模式是对象的结构模式.享元模式以共享的方式高效地支持大量的细粒度对象. 一.享元模式的结构 享元模式采用一个共享来避免大量拥有相同内容对 ...

  9. .NET设计模式(13):享元模式(Flyweight Pattern)(转)

    摘要:面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题.但是在某些情况下,对象的数量可能会太多,从而导致了运行时的代价.那么我们如何去避免大量细粒度的对象,同时又不影响客户程序使用面 ...

随机推荐

  1. win7锁定到任务栏的路径在哪里

    You can find pinned apps in: %AppData%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar ...

  2. Javascript 笔记与总结(2-13)定时器 setTimeout 和 setInterval

    定时器可以让 js 效果每隔几秒钟执行一次或者 n 秒之后执行某一个效果.定时器不属于 javascript,是 window 对象提供的功能. setTimeout 用法: window.setTi ...

  3. Web 在线文件管理器学习笔记与总结(9)下载文件

    ① 普通形式的文件可以使用超链接形式下载 <a href = '下载文件名'>点击下载</a> ② 如果下载图片.html 等类型的文件,使用header() 函数发送网页头信 ...

  4. 20145317彭垚 《Java程序设计》第10周学习总结

    20145317彭垚 <Java程序设计>第10周学习总结 教材学习内容总结 网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网 ...

  5. hdf第二周,每天加班,周末加班,周日健身

    ----------------------------------------------------------------------------- 受到挫折,写一些简单的练习,增加成就感 放大 ...

  6. JAVA的覆盖、继承和多态的详细解说.this和super的用法

    1. 继承: (1)子类的构造方法一定会调用父类的构造方法. (2)任何子类构造方法第一行肯定是this();或者super();两个择一. this();调用本类的其它构造方法.(传递相应参数调用相 ...

  7. url匹配和match()方法

    下面的全局匹配可以找到字符串中的所有数字: "1 plus 2 equals 3".match(/\d+/g) // 返回 ["1", "2" ...

  8. [Virtualization][SDN] VXLAN到底是什么 [转]

    写在转发之前: 几个月以前,在北大机房和燕园大厦直接拉了一根光钎.两端彼此为校园内公网IP.为了方便连接彼此机房,我做个一个VPN server在燕园的边界,北大机房使用client拨回.两个物理机房 ...

  9. Bluetooth SDP介绍

    目录 1. 概念 2. 服务记录(Service Record) 3. 服务属性(Service Attribute) 4. 服务类(Service Class) 5. 服务查找 5.1 UUID 5 ...

  10. 002_base64的编码实现

    一.先贴一张ASCII码的图 二.再贴一张base64转换规则的图 二.python代码实现.