想起我那本《javascript设计模式》给落在上北京的火车上了,心嗵嗵的惋惜啊。今天在图书馆就重新从书架上拿出来翻了翻,仔细看了下享元模式的原理,下面是描述书中的实现方式,最后提出点我的一点看法。
享元模式的核心思想就在于“元”,即是“关键内容”,其他附加内容都拆分到其他对象容器里。它适用的场合是当数据量庞大的时候,该怎么去更好的节省内存来储存每一个数据。比如:要存储一个城市的全部车辆的登记信息,宝马、林肯、QQ、熊猫……何其多啊。如果按照我们普通的方式来存储,就是给每一辆车都创建一个对象来存储车辆的信息:
[javascript]
var Car = function(make,model,year,owner,tag,renewDate){
this.make=make;
this.model=model;
this.year=year;
this.owner=owner;
this.tag=tag;
this.renewDate=renewDate;
}
Car.prototype = {
getMake:function(){
return this.make;
},
getModel:function(){
return this.model;
},
getYear:function(){
return this.year;
},
transferOwner:function(owner,tag,renewDate){
this.owner=owner;
this.tag=tag;
this.renewDate=renewDate;
},
renewRegistration:function(renewDate){
this.renewDate=renewDate;
}
}
[/javascript]
这是我们通常会想到的办法。这个方法对于数据量小到没多大的影响,随着时间的推移,福特车都卖出去的时候,这个数据量就非常庞大了,越来越难驾驽了,迟早要消耗完可怜的计算机内存资源。为此,我们需要优化数据存储的结构和方式,解放计算机的内存消耗。对此,书中通过使用享元模式来重构数据存储,将核心数据和附加数据相分离,来减少上面代码中Car类的每一个实例对象数据的大小。对此,书中提出了下面的实现方式:
[javascript]
//包含核心数据的Car类
var Car=function(make,model,year){
this.make=make;
this.model=model;
this.year=year;
}
Car.prototype={
getMake:function(){
return this.make;
},
getModel:function(){
return this.model;
},
getYear:function(){
return this.year;
}
}
//中间对象,用来实例化Car类
var CarFactory=(function(){
var createdCars = {};
return {
createCar:function(make,model,year){
var car=createdCars[make+"-"+model+"-"+year];
//本人修改了下,精简了代码
return car ? car : createdCars[make + '-' + model + '-' + year] =(new Car(make,model,year));
}
}
})();
//数据工厂,用来处理Car的实例化和整合附加数据
var CarRecordManager = (function() {
var carRecordDatabase = {};
return {
addCarRecord:function(make,model,year,owner,tag,renewDate){
var car = CarFactory.createCar(make, model, year);
carRecordDatabase[tag]={
owner:owner,
tag:tag,
renewDate:renewDate,
car:car
}
},
transferOwnership:function(tag, newOwner, newTag, newRenewDate){
var record=carRecordDatabase[tag];
record.owner = newOwner;
record.tag = newTag;
record.renewDate = newRenewDate;
},
renewRegistration:function(tag,newRenewDate){
carRecordDatabase[tag].renewDate=newRenewDate;
},
getCarInfo:function(tag){
return carRecordDatabase[tag];
}
}
})();
[/javascript]
上面的实现方式就是享元模式了,通过将主要的核心数据和附加数据拆分开来处理,减少核心类Car的数据存储量。但是,上面的实现方式是以复杂为代价的,而且在操作数据的时候,需要多级的对象调用,如果是频繁操作数据的话,上面的实现方式也同样是一个内存消耗隐患,特别是对make、model、year数据的操作。而且它还是需要为每一辆车实例化一个对象,存储对象需要分配较多的内存唷。
为此,就这个需求来说,我想为何不简单点,通过统一使用一个数据存储对象来存储所有的车辆的数据,通过tag作为标识呢。下面是我所想到的实现方式:
[javascript]
var CarManager=(function(){
var carDatabase={};
return {
addCarRecord:function(make,model,year,owner,tag,renewDate){
var car=carDatabase[tag];
if(car){ return car;}
else{
carDatabase[tag]={
make:make,
model:model,
year:year,
owner:owner,
tag:tag,
renewDate:renewDate
}
}
},
transferOwnership:function(tag, newOwner, newTag, newRenewDate){
var car=carDatabase[tag];
car.owner=newOwner;
car.tag=newTag;
car.renewDate=newRenewDate;
},
renewRegistration:function(tag,newRenewDate){
carDatabase[tag].renewDate=newRenewDate;
},
getCarInfo:function(tag){
return carDatabase[tag];
}
}
})();
[/javascript]
上面的代码简洁明了,把数据都存储在carDatabase这个对象里,并通过tag作为标识来识别每一部车辆的数据信息,而且在操作数据的时候,查询对象信息属性的级数也少。同时,它不需要为每一辆车实例化一个对象。这在优化内存消耗上是一个比较好的方式。
通过测试发现,在实例化的性能方面,第一种方式是最快的,第二种最慢。出现这个差异是不言而喻的。但是第一种方式对数据量大的时候内存消耗最大。《测试页面》
最后分析的真不错,谢谢!!