享元模式:避免对象间用用相同内容造成多余的开销。
例如一个简单的新闻翻页功能,页面加载后,异步请求新闻数据,然后创建所有条新闻并插入页面中,需要显示哪一页就将对应页的新闻显示,其他的新闻隐藏......
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>javascript设计模式_享元模式</title>
<style>
.container div{
width: 200px;
height: 80px;
line-height: 80px;
background-color: gray;
color: white;
margin-bottom: 20px;
}
</style>
<script>
// article为获取到的数据
var article=["我是文章内容的标题1","我是文章内容的标题2","我是文章内容的标题3","我是文章内容的标题4","我是文章内容的标题5",
"我是文章内容的标题6","我是文章内容的标题7","我是文章内容的标题8","我是文章内容的标题9","我是文章内容的标题10","我是文章内容的标题11","我是文章内容的标题12",
];
window.onload=function(){
// oldFun();
newFun();
}
function oldFun(){
var dom = null,//缓存创建的新闻标题元素
paper = 0,//当前页数
num = 5, //每页显示新闻数目
i = 0,//创建新闻元素时保存变量
len = article.length; //新闻数据的长度
for(;i<len;i++){
dom=document.createElement('div');//创建包装新闻标题元素
dom.innerHTML=article[i];//向元素中添加新闻标题
if(i>=num){
dom.style.display='none';//超出第一页新闻隐藏
}
document.getElementById('container').appendChild(dom);//添加到页面中
}
//下一页事件绑定
document.getElementById('nextPage').onclick=function(){
var div=document.getElementById('container').getElementsByTagName('div');//获取所有新闻标题
var j=k=n=0;//j、k循环变量,n当前页显示的第一个新闻序号
n=++paper%Math.ceil(len/num)*num;//获取当前页显示的第一个新闻序号
for(;j<len;j++){
div[j].style.display='none';//隐藏所有新闻
}
for(;k<5;k++){
if(div[n+k]){
div[n+k].style.display="block";//显示当前页新闻
}
}
}
}
function newFun(){
//创建一个操作函数
var flyWeight=function(){
var created=[];//存储已创建的元素的数组
return {
getDiv:function(){
if(created.length<5){//当元素不足5个这种基本条件的时候,通过create()函数继续新建一个dom节点
return create();
}else{//否则,复用数组中的dom节点
var div=created.shift();//获取最后一个元素
created.push(div);//插入到最后面
return div;//返回重新编排的元素节点
}
}
}
function create(){ //用于页面初始化时创建元素的函数
var dom=document.createElement('div');
document.getElementById('container').appendChild(dom);//将容器插入新闻列表容器中
created.push(dom);//存到已创建元素数组中
return dom;//返回新创建的元素节点
}
}();//注意,立即执行!
var page=0,//当前页数
num=5,//一页显示条目数
len=article.length;//数据长度
for(var i=0;i<5;i++){
if(typeof(article[i])!=undefined){//如果有数据
flyWeight.getDiv().innerHTML=article[i];//通过享元函数写入数据内容
}
}
document.getElementById('nextPage').onclick=function(){
if(article.length<5){
return;//数据小于基本要求5条,不执行操作
}else{
var n=++page*num%len;//获取当前页第一条新闻的下标
for(var j=0;j<5;j++){
if(article[n+j]){//如果大于5条之后还有数据
flyWeight.getDiv().innerHTML=article[n+j];//通过享元函数写入数据内容
}
else if(article[n+j-len]){
flyWeight.getDiv().innerHTML=article[n+j-len];//如果第N页不够5条,从头开始补上
}
else{
flyWeight.getDiv().innerHTML=" ";
}
}
}
}
}
</script>
</head>
<body>
<div id="container" class="container">
<p>显示新闻</p>
<button id="nextPage">下一页</button>
</div>
</body>
</html>
所有的新闻都有相同的结构,只是内容不同,创建几百条新闻同时插入页面并造成的多余的开销在低版本的浏览器中会严重影响其性能
对于相同结构造成的多余的开销问题,可以使用享元模式解决。
主要对其数据、方法共享分离,将其数据和方法分为内部数据、内部方法和外部数据、外部方法。将内部数据与内部方法中相似或共有的数据和方法提取出来减少开销。