再起航,我的学习笔记之JavaScript设计模式11(外观模式)

经过一段时间的学习与分享,我们对创建型设计模式已经有了一定的认识,未来的一段时间里我们将展开新的篇章,开始迈入结构性设计模式的学习。

结构性设计模式与创建型设计模式不同,结构性设计模式更偏向于关注如何将类和对象组合成更大、更复杂的结构,以简化设计。

外观模式

外观模式(Facede): 为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易。在JavaScript中有时也会用于对底层结构兼容性做统一的封装来简化用户使用。

这个含义看上去有点抽象,下面我将通过示例为大家演示外观模式,但是在了解外观模式之前,我们先讲一下,我们接下来例子中会演示的dom0级事件和dom2级事件

DOM0级事件

DOM0级事件主要是指on+事件类型,比如我们的onclick事件。

其实在W3C标准里是是没有DOM0级的。但是在我们平时阅读的时候可能会读到DOM0级(DOM Level0)的字眼。实际上,DOM0级标准是不存在的,所谓的DOM0级是DOM历史坐标中的一个参照点而已,具体说呢,DOM0级指的是IE4和Netscape 4.0这些浏览器最初支持的DHTML,大概2000年的时候争论过DOM0的问题,最后结论大概是,没有官方形成此标准。

dom0级事件有个特点就是后定义的事件处理会覆盖前面的。我们来看一个示例:

document.getElementById('btn').onclick=function(){
	console.log('第一个点击事件');
}
document.getElementById('btn').onclick=function(){
	console.log('第二个点击事件');
}

现在我们看看结果,我们发现后面定义的事件果然覆盖了前面的事件。

DOM2级事件

DOM2级事件主要是指addEventListener(events,handler,boolean),removeEventListener(events,handler)这类事件

当然DOM2级事件的特点是不会覆盖自身,而且和DOM0级事件也能共存。我们来看下面的示例。

document.getElementById('btn').addEventListener("click",function(){
	console.log("监听第一个点击事件");
})
document.getElementById('btn').addEventListener("click",function(){
	console.log("监听第二个点击事件");
})

我们可以看到,我们为btn绑定的两个点击事件均被触发。

此处我们只简单介绍这两个级别的事件其他事件如果有兴趣大家可以自行查阅资料

那么我们现在讲的DOM0级事件和DOM2级事件和外观模式又有什么联系呢?
我们都知道浏览器的兼容是个很麻烦的事情,就比如我们的addEventListener监听事件在老版本的IE浏览器是不支持的,所以那些老版本的浏览器我们要用attachEvent来实现,当然如果碰到了不支持DOM2级事件处理的浏览器,那么我们只能用on事件方法去绑定事件

所以这个时候我们就可以用外观模式去封装他们。

外观模式

如同我们定义里说的一样为一组复杂的子系统接口提供一个更高级的统一接口,我们通过下面这个示例为大家演示外观模式

function addEvent(dom,type,fn){
	//对于支持DOM2级事件并且支持监听事件的浏览器我们使用监听事件
	if(dom.addEventListener){
		dom.addEventListener(type,fn);
	}//对于支持DOM2级事件但不支持监听事件的浏览器我们用attachEvent方法
	else if(dom.attachEvent){
		dom.attachEvent('on'+type,fn);
	}//对于不支持DOM2级事件的浏览器,我们只能用on+'事件名'的DOM0级事件方式
	else{
		dom['on'+type]=fn;
	}
}

我们来试一试

var btn=document.getElementById('btn');
addEvent(btn,'click',function(){
	console.log("绑定第一个事件")
})
addEvent(btn,'click',function(){
	console.log("绑定第二个事件")
})

因为浏览器版本支持监听事件所以我们触发了第一种方法

进一步解决兼容问题

从我们上面的介绍其实我们可以进一步延伸,很多兼容问题我们都可以通过外观模式去解决,比如低版本的IE不兼容preventDefault方法和target属性,那么我们同样可以通过外观模式来解决

var getEvent=function(event){
	//标准浏览器返回event,IE返回window.event
	return event||window.event;
}
var getTarget=function(event){
	var event=getEvent(event);
	//标准浏览器返回target,IE返回srcElement
	return event.target||event.srcElement;
}
var preventDefault=function(event){
	var event=getEvent(event);
	//标准浏览器
	if(event.preventDefault){
		event.preventDefault();
	}//IE浏览器
	else{
		event.returnValue=false;
	}
}

我们来试一下

document.onclick=function(e){
	//阻止默认行为
	preventDefault(e);
	//获取事件源目标对象
	if(getTarget(e)!==document.getElementById('btn')){
		console.log("阻止");
	}
}

我们看到只要在我们btn按钮之外的地方点击,这个事件都会输出阻止

总结

通过外观模式,对接口的二次封装隐藏其复杂性,并简化其使用是一种不错的时间,当然这种实践多少都会增加一些资源的开销以及程序的复杂度。不过这种开销对于使用成本来说是可以忽略的。

外观模式是对接口方法的外层包装,以供上层代码调用。因此有时外观模式封装的接口方法不需要接口的具体实现,只需要按照接口使用规则使用即可。这也是对系统与客户之间的一种松散耦合。使得系统与客户之间不会因结构的变化而互相 影响。
也谢谢大家看到这里:)如果你觉得我的分享还可以请点击推荐,分享给你的朋友让我们一起进步~

好了以上就是本次分享的全部内容,本次示例参考自JavaScript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。

欢迎转载,转载请注明作者,原文出处。

posted @ 2017-08-23 08:04  东城慕水  阅读(627)  评论(0编辑  收藏  举报