为了账号安全,请及时绑定邮箱和手机立即绑定

享元模式

2020.09.11 10:15 6662浏览

享元模式

以共享的方式降低大量重复对象在内存中的开销,就叫做享元模式。
享元模式能做到共享的关键是区分内部状态和外部状态:内部状态是可以共享的对象,外部状态会随着环境的改变而改变,不可共享。

使用场景

假如有一个下围棋的小游戏,虽然围棋一共有361枚棋子,但从颜色上区分,只有黑白两种,因此,黑白棋子各有一个就足够了。

例子:

// 创建棋子的类
var Chess=function(color){
  this.color=color;
}
// 落子的函数
Chess.prototype.put=function(x,y){
  console.log('在['+x+','+y+']位置放了一个'+this.color+'子');
}

// 享元工厂函数
// 负责创建和管理棋子
var ChessFactory=(function(){
  // 可共享的内部状态
  var black=new Chess('黑'),
      white=new Chess('白');
  return function(color){
    if(color==='黑'){
      return black;
    }else{
      return white;
    }
  }
})();

// 测试
var p1=ChessFactory('黑');
p1.put(1,1); 
// 输出:在[1,1]位置放了一个黑子

var p2=ChessFactory('白');
p2.put(2,2); 
// 输出:在[2,2]位置放了一个白子

var p3=ChessFactory('黑');
p3.put(3,3); 
// 输出:在[3,3]位置放了一个黑子

上例中可以看到,只需要两个对象便完成了创建361枚棋子的功能。

对象池技术

享元模式是对象池技术的重要实现方式。除此以外,对象池技术的应用非常广泛,在前端开发中,对象池更多的是应用在对DOM的操作上。

假如开发一个搜索功能,当搜索“世界名人”的时候,页面里出现了3条结果;当再搜索“世界名著”的时候,页面中出现了6条结果。
如果按照对象池技术的思路,第一次搜索时创建的3个DOM元素,并不会删除,而是放进对象池中备用,
如此一来,第二次搜索时,只需再创建3个DOM元素,而不是6个。

例子:

<input type="text" /> <button>查询</button>
<div></div>

// 对象池工厂函数
// 负责创建和管理元素
var ObjectPoolFactory = function () {
 // 对象池
 var objectPool = [];

 var creat = function () {
   var p =
     objectPool.length === 0
       // 若对象池中没有元素,则创建
       ? document.createElement("p")
       // 若对象池中有元素,则直接使用
       : objectPool.shift();
   document.querySelector("div").appendChild(p);
   return p;
 };
 
 // 将元素回收至对象池中
 var recover = function (ele) {
   objectPool.push(ele);
 };
// 暴露特性函数(特指可以访问闭包的函数)
 return {
   creat: creat,
   recover: recover,
 };
};

document.querySelector("button").addEventListener("click", function () {
 var domFactory = ObjectPoolFactory();
 var val = document.querySelector("input[type=text]").value;

 // 临时保存已创建的Dom元素
 var list = [];
 document.querySelector("div").innerHTML = "";

 if (val === "世界名人") {
   for (var item of ["爱因斯坦", "列夫托尔斯泰", "孔子"]) {
     var domElement = domFactory.creat();
     domElement.innerHTML = item;
     list.push(domElement);
   }
 } else if (val === "世界名著") {
   for (var item of ["复活","简爱","童年","巴黎圣母院","飘","红与黑"]) {
     var domElement = domFactory.creat();
     domElement.innerHTML = item;
     list.push(domElement);
   }
 }

 for (var domItem of list) {
   domFactory.recover(domItem);
 }
});

如有错误,欢迎指正,本人不胜感激。

点击查看更多内容

本文首次发布于慕课网 ,转载请注明出处,谢谢合作

1人点赞

若觉得本文不错,就分享一下吧!

评论

相关文章推荐

正在加载中
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消