本篇文章参考书籍《JavaScript设计模式》–张容铭
前言
铁汁们,我又来了,上节的组合模式,各位乱了没?不慌哈,这一节我们一起学个更乱的,就不会觉得上一个乱了。
大家学东西肯定逃不开一个问题,性能。实现功能的方法千千万,为什么有的方法好,有的方法不合适?很大一部分原因是性能问题,性能这东西,平时不注意,爆发起来可是灾难性的,页面崩溃怕不怕,卡顿怕不怕,这些都是对用户特别不友好的问题。
最关键的还是不好定位,不好修改,一旦出现,肯定涉及重构,解决成本太大。夫病已成而后药之,乱已成而后治之,譬犹渴而穿井,斗而铸锥,不亦晚乎?
享元模式
主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
举个例子,页面上展示新闻,每页 5 条,想看更多的新闻,需要翻页。这个例子就可以用到享元模式,首先需要一个操作方法。
var Flyweight = function() {
//已创建元素
var created = [];
//创建一个新闻包装容器
function creat() {
var dom = document.creatElement('div');
//将容器插入新闻列表容器中
document.getElementById('container').appendChild(dom);
//缓存新创建的元素
created.push(dom);
//返回创建的新元素
return dom;
}
return {
//获取创建新闻元素方法
getDiv: function() {
//如果已创建的元素小于当前页元素总个数,则创建
if(created.length < 5) {
return create();
} else {
//获取第一个元素,并插入最后面
var div = created.shift();
created.push(div);
return div;
}
}
}
}
上面我们创建了个享元类,接下来由于每页显示 5 条,所有我们创建 5 个元素,保存在享元类内部,通过享元类的 getDiv 来获取创建的元素,享元类内部的数据和方法完成后,我们需要实现外部数据了。
var paper = 0;
num = 5;
len = article.length;
//添加5条新闻
for(var i = 0; i < 5; i++) {
if(article[i]) {
Flyweight.getDiv().innerHTML = article[i];
}
}
接下来需要给下一页绑定一个事件
//下一页按钮绑定事件
document.getElementById('next_page').onclick = function() {
//如果新闻不足5条,则返回
if(article.length < 5) return;
var n = ++paper * num % len, //获取当前页第一条新闻索引
j = 0;
//插入五条新闻
for(; j < 5; j++) {
//如果存在 n+j 条则插入
if(article[n + j]) {
Flyweight.getDiv().innerHTML = article[n + j];
//否则插入起始位置第 n + j - len 条
} else if(article[n + j - len]) {
Flyweight.getDiv().innerHTML = article[n + j - len];
//如果都不存在则插入空字符串
} else {
Flyweight.getDiv().innerHTML = '';
}
}
}
通过享元模式,我们进入页面后只创建5个元素,不用每次翻页的时候,都需要重新创建了。
应用场景
享元模式在面向对象编程中是很常见的,比如游戏当中,每个角色的移动方法,肯定都是相同的,我们就可以创建一个享元类。
var FlyWeight = {
moveX: function(x) {
this.x = x;
},
moveY: function(y) {
this.y = y;
}
}
其他任何角色都可以通过继承的方式实现,比如放英雄继承移动方法。
//创建一个英雄类,继承移动方法
var Hero = function(s, y, c) {
this.x = x;
this.y = y;
this.color = c;
}
Hero.prototype = FlyWeight;
Hero.prototype.changeC = function(c) {
this.color = c;
}
//创建一个怪物类,继承移动方法
var Monster = function(x, y, r) {
this.x = x;
this.y = y;
this.r = r;
}
Monster.prototype = FlyWeight;
Monster.prototype.changeR = function(r) {
this.r = r;
}
接下来创建实例
//创建英雄实例
var hero = new Player(5, 6, 'red')
hero.moveX(6);
hero.moveY(7);
console.log(hero); //{x: 6, y: 7, color: 'red'}
//创建怪物实例
var monster = new Player(2, 3, 4)
monster.moveX(3);
monster.moveY(4);
console.log(monster); //{x: 3, y: 4, r: 2}
各位,本节结束,我们就介绍完了所有的结构型的设计模式,结构型的设计模式目的在将类,对象等,组合成更复杂的结构来应对需求,应用设计模式可以简化其设计方案,让复杂的结构可以变得更合理,易读懂。