享元模式
“享元”,被共享的单元,即复用对象,节省内存,注意前提是享元对象是不可变对象。
用一天的时间,抽空看完一种设计模式,或者两天,还是有收获的,我们需要耐心,这个从长远来说,不算慢的。
个人感觉这个享元模式,初步看上去,大概可以理解为一种写代码的良好习惯,性能优化、去掉冗余,在代码开发时候,要避免影响性能的不良习惯。
简单概括就是 dom 创建加载,变量,缓存,代码重用 等等能节省代码执行开支的地方就去优化,去节省。
在编程语言中共有的的理念即:抽离,封装,继承,多态,享元模式也蕴藏了此理念。
享元模式的基本概念:
享元是一种结构型设计模式,它允许你在消耗少量内存的情况下支持大量对象。
模式通过共享多个对象的部分状态来实现上述功能。换句话来说,享元会将不同对象的相同数据进行缓存以节省内存
用一个简单的例子,我们看一下,找找感觉,这个设计模式 很基础,甚至感觉是一种开发理念。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 未经优化的 tooltip 类
let Tooltip = function (targetElement, text) {
this.target = targetElement;
this.text = text;
this.delayTimeout = null;
this.delay = 1500;
// create the HTML
this.element = document.createElement("div");
this.element.style.display = "none";
this.element.style.position = "absolute";
this.element.className = "tooltip";
document.getElementsByTagName("body")[0].appendChild(this.element);
// attach the event
var that = this;
addEvent(this.target, "mouseover", function (e) {
that.startDelay(e);
});
addEvent(this.target, "mouseout", function (e) {
that.hide();
});
};
Tooltip.prototype = {
startDelay: function (e) {
if (this.delayTimeout == null) {
let that = this;
let x = e.clientX;
let y = e.clientY;
this.delayTimeout = setTimeout(function () {
this.show();
}, this.delay);
}
},
show: function (x, y) {
clearTimeout(this.delayTimeout);
this.delayTimeout = null;
this.element.style.left = x + "px";
this.element.style.top = y + 20 + "px";
this.element.style.display = "block";
},
hide: function () {
clearTimeout(this.delayTimeout);
this.delayTimeout = null;
this.element.style.display = "none";
}
};
上述的这段代码,意味着,我们每每使用到一个提示,就需要创建一个提示 dom 元素,那一个项目操作下来,多少个都有可能,几百几千个的话,是不是会有点崩溃的,性能会很差,浏览器开销会很大。从良好的开发习惯上来讲,这个肯定要优化的,要把示例抽离,只创建一个 提示 dom,在需要的时候,控制展示不同的内容就好了。所以基础单元,要和数据单元进行分离。
在实际应用中,这个唯一创建的提示 dom 这个逻辑,这个行为,就是享元,共享单元。 而我们需要用的动态数据变量,需要抽离出来单独处理,平常代码开发,我们经常提到的,代码功能独立性,就像积木,就像电子元器件,开发思想的重要性。
下面我们看一下,设计模式-享元模式对上面这段案例的处理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// manager
let TooltipManager = (function () {
let storeInstance = null;
let Tooltip = function () {
this.delayTimeout = null;
this.delay = 1500;
// create the HTML
this.element = document.createElement("div");
this.element.style.display = "none";
this.element.style.position = "absolute";
this.element.className = "tooltip";
document.getElementsByTagName("body")[0].appendChild(this.element);
};
Tooltip.prototype = {
startDelay: function (e) {
if (this.delayTimeout == null) {
let that = this;
let x = e.clientX;
let y = e.clientY;
this.delayTimeout = setTimeout(function () {
this.show(x, y, text);
}, this.delay);
}
},
show: function (x, y, text) {
clearTimeout(this.delayTimeout);
this.delayTimeout = null;
this.element.innerHTML = text;
this.element.style.left = x + "px";
this.element.style.top = y + 20 + "px";
this.element.style.display = "block";
},
hide: function () {
clearTimeout(this.delayTimeout);
this.delayTimeout = null;
this.element.style.display = "none";
}
};
return {
addTooltip: function (targetElement, text) {
let tt = this.getTooltip();
addEvent(targetElement, "mouseover", function (e) {
tt.startDelay(e, text);
});
addEvent(targetElement, "mouseout", function (e) {
tt.hide();
});
},
getTooltip: function () {
if (storeInstance == null) {
storeInstance = new Tooltip();
}
return storeInstance;
}
};
})();
上面这个Tooltip类和未处理前做一个对比,去进一步了解享元模式。