JavaScript注册机的实现(类似于观察者模式)
之前一直在做一个webgis的前端开发,用到了诸如ajax,WS等等技术。在项目结束后,自己的总结过程中,有了一个对javaScript 控制事件触发的模型的概念,这段时间有拜读了下设计模式中的观察者模式,总算是有了些成熟的想法。
这些想法是我在做B/S的底层地图控制的时候的一些想法,比如一个用户在移动地图的同时会触发多个事件,但是这个触发的事件是动态的。在之前的老办法就是通过全局变量来控制,但是用全局变量的话,程序的可控制性太差,一点改动就会引起其他地方的改动,这个缺点在后期的维护的时候尤其明显。所有就有了这个思考的结果。
废话不多说,直接上代码:
上面的截图是我用来做的测试界面,整体的想法是:用一个注册机实现多个事件的同时触发,并用这个注册机去控制当前注册的事件。如上图所示,举例假设一共有三个待注册的事件,用一个注册机的对象来实现对这触发三个事件的控制。
链表类:
LinkedList();
这个自定义的链表类,类似于C#中的链表,代码会在文章后面的贴出来。
自定义注册机类:
this.event=""; //事件执行代码
this.eventList=new LinkedList();//用于储存事件的链表 属于注册机的属性
this.addEvent=function(evnet){//将事件名加到事件链表中
for(var itr = this.eventList.iterator();itr.hasNext(); )//如果id有重复的事件者不重复注册
{
var itm = itr.next();
if(itm.id==evnet.id){
return "";
}
}
this.eventList.add(evnet);
}
this.delEvent=function(id){//按照事件id注销事件
var i=0;
for(var itr = this.eventList.iterator();itr.hasNext(); )
{
var itm = itr.next();
if(itm.id==id){
this.eventList.remove(i);//删除链表中的元素
return "";
}
i++;
}
}
this.doEvent=function(){ //循环执行注册机内已经注册的事件
for(var itr = this.eventList.iterator();itr.hasNext(); )
{
var itm = itr.next();
eval(itm.value);//通过eval函数执行 函数字符串
}
}
}
function event(){
this.id="";//事件标记id
this.value="alert(\"默认事件!\")"; //事件值也就是要执行的 代码或者是事件名称
}
测试页面:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>js注册机</title>
<script language="javascript" type="text/javascript">
//链表对象-----------------------------------------------------------------------------------------------------------------------
function Entry(next, data)
{
this.next = next
this.data = data
}
function Iterator(node)
{
this.cousor = node
this.hasNext = function ()
{
return (this.cousor.next != null);
}
this.next = function ()
{
var rt = this.cousor.next
this.cousor = this.cousor.next
return rt.data
}
this.replaceData=function(datar){
this.cousor.data=datar
}
}
function LinkedList()
{
this.head = new Entry(null, null)
this.size = function ()
{
var size = 0
if (this.head == null)
{
return size
}
var p = this.head.next
for(; p!=null; p = p.next)
size++;
return size;
}
this.clear = function ()
{
this.head = null
}
this.getNode = function (idx)
{
var pos = -1;
var p = this.head
while (p != null && pos < idx) {
p = p.next;
pos ++;
}
return p;
}
this.gett = function (idx)
{
return this.getNode(idx).data
}
this.add = function (data)
{
this.insert(this.size(), data)
}
this.insert = function (idx, data)
{
var p = this.getNode(idx-1); /*注意查询idx-1*/
if (p == null){
return
}
var node = new Entry(p.next, data)
p.next = node
}
this.remove = function (idx)
{
var prenode = this.getNode(idx - 1)
var node = this.getNode(idx)
if (prenode == null || node == null)
{
return null
}
prenode.next = node.next
return node.data
}
this.iterator = function ()
{
return new Iterator(this.head)
}
this.swap = function (a, b)
{
var av = this.getNode(a)
var bv = this.getNode(b)
var tmp = av.data
av.data = bv.data
bv.data = tmp
}
this.replace=function(index,data){
var j=0;
for(var itr =this.iterator(); itr.hasNext(); ){
itr.next();
if(index==j) itr.replaceData(data);
j++;
}
}
}
//链表对象-----------------------------------------------------------------------------------------------------------------------
</script>
</head>
<input type="button" onclick="registerMove()" value="注册移动事件" />
<input type="button" onclick="registerStop()" value="注册停止事件" />
<input type="button" onclick="registerClose()" value="注册关闭事件" />
<input type="button" onclick="registerAll()" value="注册所有事件" />
<br/>
<br/>
请输入删除事件的ID:<input type="textbox" id="eventDelID" /> <input type="button" onclick="registerDel()" value="删除事件" />
<br/>
<br/>
<input type="button" onclick="doEvent()" value="触发器" />
<body>
<script language="javascript" type="text/javascript">
var oneregister=new register();
function register(){
this.event=""; //事件执行代码
this.eventList=new LinkedList();//用于储存事件的链表 属于注册机的属性
this.addEvent=function(evnet){//将事件名加到事件链表中
for(var itr = this.eventList.iterator();itr.hasNext(); )//如果id有重复的事件者不注册
{
var itm = itr.next();
if(itm.id==evnet.id){
return "";
}
}
this.eventList.add(evnet);
}
this.delEvent=function(id){//将事件名加到事件链表中
var i=0;
for(var itr = this.eventList.iterator();itr.hasNext(); )//如果id有重复的事件者不注册
{
var itm = itr.next();
if(itm.id==id){
this.eventList.remove(i);
return "";
}
i++;
}
}
this.doEvent=function(){
//循环执行注册机内的事件
for(var itr = this.eventList.iterator();itr.hasNext(); )
{
var itm = itr.next();
eval(itm.value);
}
}
}
//事件对象
function event(){
this.id="";
this.value="alert(\"默认事件!\")";
}
function registerMove(){
var e=new event();
e.id="move";
e.value="alert(\"执行了移动事件!\")";
oneregister.addEvent(e);
}
function registerStop(){
var e=new event();
e.id="stop";
e.value="alert(\"执行了停止事件!\")";
oneregister.addEvent(e);
}
function registerClose(){
var e=new event();
e.id="close";
e.value="eventClose()";
oneregister.addEvent(e);
}
function registerAll(){
var e=new event();
e.id="move";
e.value="alert(\"执行了移动事件!\")";
oneregister.addEvent(e);
var e=new event();
e.id="stop";
e.value="alert(\"执行了停止事件!\")";
oneregister.addEvent(e);
var e=new event();
e.id="close";
e.value="eventClose()";
oneregister.addEvent(e);
}
function eventClose(){
alert("执行了关闭事件");
}
//删除事件
function registerDel(){
var id=document.getElementById('eventDelID').value;
oneregister.delEvent(id);
}
//触发器
function doEvent(){
oneregister.doEvent();
}
</script>
</body>
</html>