示例:工具提示对象享元模式应用

<!DOCTYPE html>
<html>
<head>
<title>工具提示(享元模式)</title>
<meta charset="utf-8">
<script src="Library.js"></script>
</head>
<body>
<a id="link-id1" href="">1111111</a><a id="link-id2" href="">222222</a>
<script>
/**
* 示例:工具提示对象
*
* 在HS对象需要创建HTML内容这种情况下,享元模式特别有用。那种会生成DOM元素的对象如果数目众多的话,会占用过多内存,使网页陷入泥沼。采用享元模式后,只需创建少许这种对象即可,所有需要这种对象的地方都可以共享它们。工具提示就是一个典型的例子。
*/

// 未经优化的Tooltip类
// Tooltip class, un-optimized
var Tooltip = function (targetElement, text) {
this.target = targetElement;
this.text = text;
this.delayTimeout = null;
this.delay = 500;

this.element = document.createElement('div');
this.element.style.display = 'none';
this.element.style.position = 'absolute';
this.element.className = 'tooltip';
document.body.appendChild(this.element);
this.element.innerHTML = this.text;

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) {
var that = this,
x = e.clientX,
y = e.clientY;
this.delayTimeout = setTimeout(function () {
that.show(x, y);
}, 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';
}
};

var link1 = $('link-id1'),
link2 = $('link-id2');
var tt = new Tooltip(link1, 'Lorem ipsum....');

// 作为享元的Tooltip
/*
把Tooltip类转化为享元需要做三件事:把外在数据从Tooltip对象中删除;创建一个用来实例化Tooltip的工厂;创建一个用来保存外在数据的管理器。在这个例子,我们可以用一个单体同时扮演工厂和管理器的角色。此外,由于外在数据可以作为事件侦听器一部分保存,因此没有必要使用一个中心数据库。
*/

// TooltipManager singleton, a flyweight factory and manager
var TooltipManager = (function () {
var storedInstance = null;

// Tooltip class, as aflyweight
var Tooltip = function () {
this.delayTimeout = null;
this.delay = 500;

this.element = document.createElement('div');
this.element.style.display = 'none';
this.element.style.position = 'absolute';
this.element.className = 'tooltip';
document.body.appendChild(this.element);
};
Tooltip.prototype = {
startDelay: function (e, text) {
if (this.delayTimeout === null) {
var that = this,
x = e.clientX,
y = e.clientY;
this.delayTimeout = setTimeout(function () {
that.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) {
// Get the tooltip object
var tt = this.getTooltip();
// Attach the events
addEvent(targetElement, 'mouseover', function (e) {
tt.startDelay(e, text);
});
addEvent(targetElement, 'mouseout', function (e) {
tt.hide();
});
},
getTooltip: function () {
if (storedInstance === null) {
storedInstance = new Tooltip();
}
return storedInstance;
}
};
})();

// Tooltip usage
TooltipManager.addTooltip($('link-id2'),'fuck your ass');
/*
上面的Tooltip类删除了原来的构造函数的所有参数以及注册事件处理器的代码。而startDelay和show方法则各增加了一个新的参数,这样一来,要显示的文字就可以作为外在数据传给他们。

这个单体有两个方法,分别体现了他的两种角色,getTooltip是工厂方法,它与你之前见到过的其他享元的生成方法差不多。addTooltip则是管理器方法,它先获取一个Tooltip对象,然后后分别把两个匿名函数注册为目标元素的mouseover和mouseout事件侦听器。这个例子用不着创建中心数据库,因为那两个匿名函数中生成的闭包已经保存了外在数据。
*/

/*
现在生成的DOM元素已减至一个。这很重要,假如你想为工具提示添加阴影或iframe垫片等特性,那么每个Tooltip对象需要生成5-10个DOM元素。要是不把它实现为享元的话,网页将被成百上千个工具提示压垮。此外,享元模式的应用还减少了对箱内部保存的数据。
*/
</script>
</body>
</html>
原文地址:https://www.cnblogs.com/webFrontDev/p/2978523.html