Skip to main content
 首页 » 编程设计

javascript享元模式应用之工具提示对象

2022年07月16日29Free-Thinker
<!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/archive/2013/03/24/2978523.html