享元模式主要是分析应用程序的数据,分出可共享的部分和不可共享的部分,对于可共享的部分,我们可以放到一个地方单独维护。让多个对象共享,其他的数据则每个对象自己维护。
//学生可共享的信息
function infoShare(student,schoolName) {
this.identity = student;
this.schoolName = schoolName;
}
//享元管理器,包装成匿名函数主要是不把_infoShareObj 暴露出去。
var InfoShareManager = (function(){
var _infoShareObj = {};//去掉var可以把_infoShareObj导出到全局看他的值
return {
getShareInfo:function(student,schoolName) {
var key = student+schoolName;
if(_infoShareObj[key]){
return _infoShareObj[key];
}
else{
return (_infoShareObj[key] = new infoShare(student,schoolName));
}
}
}
}())
//学生类
function student(name,age,student,schoolName) {
this.name = name ;
this.age = age;
this.dataShare = InfoShareManager.getShareInfo(student,schoolName);
}
//客户端类
function client() {
var data = [];
console.time('start');
for(var i = 0;i<100;i++){
data.push(new student("a",i,i%2,i%2));
}
console.timeEnd('start');
}
client();
上面代码中,_infoShareObj 只有两个对象,分别是键值为0和2.这两个对象给100个学生共享。通过执行时间发现,利用享元会导致执行时间变长,可能是每次都需要调用其他函数和访问其他变量的原因,但是他的确节省了内存。
开始设计的时候觉得享元可能不会被改变,但是如果有特殊情况的时候,需要改变享元的数据,就会比较麻烦,因为他是共享的,修改享元也会影响其他的用户。所以利用linux下的进程复制的知识,写时复制的技术解决这个问题。
function infoShare(student,schoolName) {
this.identity = student;
this.schoolName = schoolName;
}
var InfoShareManager = (function(){
var _infoShareObj = {};//去掉var可以把_infoShareObj导出到全局看他的值
return {
getShareInfo:function(student,schoolName) {
var key = student+schoolName;
if(_infoShareObj[key]){
return _infoShareObj[key];
}
else{
return (_infoShareObj[key] = new infoShare(student,schoolName));
}
}
}
}())
function student(name,age,student,schoolName) {
this.flag = false;//标记是否已经指向独立的对象
this.name = name ;
this.age = age;
this.dataShare = InfoShareManager.getShareInfo(student,schoolName);
this.setIdentity = function(identity) {
if(this.flag){
this.dataShare.identity = identity;
}
else{
this.commomSet('identity',identity);
}
};
this.commomSet = function(key,value) {//通用修改数据的方法。
var obj = {};
var dataShare = this.dataShare;
for(var index in dataShare){
obj[index] = dataShare[index];
}
obj[key] = value;
this.dataShare = obj;
this.flag = true;
};
this.getIdentity = function() {
return this.dataShare.identity;
};
this.setSchoolName = function(schoolName) {
if(this.flag){
this.dataShare.schoolName = schoolName;
}
else{
this.commomSet('schoolName',schoolName);
}
}
}
function client() {
var data = [];
console.time('start');
for(var i = 0;i<100;i++){
data.push(new student("a",i,i%2,i%2));
}
console.timeEnd('start');
data[0].setIdentity('teacher');
console.log(data[2].getIdentity(),data[0].getIdentity())
console.log(data[1].getIdentity())
debugger
}
client();