本文共 3568 字,大约阅读时间需要 11 分钟。
门面模式有两个作用:一是简化类的接口;二是消除类与使用它的客户代码之间的耦合。在javascript中,门面模式常常是开发人员最亲密的朋友。它是几乎所有javascript库的核心原则。通过创建一些使得方法让复杂系统变得更加简单易用,门面模式可以使库提供的工具更容易理解。使用这种模式,程序员可以间接地与一个子系统打交道,与直接访问子系统相比,这样做更不容易出错。
门面模式简化了诸如错误记录和跟踪页面视图统计数据这类常用的或重复性的任务。通过添加一些使得方法,它还可以让对象的功能显得更加完善。
门面模式可以用于简化复杂接口。它可以在幕后为你进行错误检查、清除不再需要的大对象,以及用一种更加易用的方式展现对象的功能
门面模式并非必不可少。同样的任务不用它也能完成。这是一种组织性的模式,它可以用来修改和对象接口,使其更便于使用。它可以让程序员过得更轻松,使他们的代码变得更容易管理。
想想计算机桌面上的那些快捷方式图标,它们就是在扮演一个把用户引导至某个地方的接口的角色,如果不借助于它们的的话,那些地方找起来会很麻烦。对于这种嵌得比较深的文件或目录,如果每次使用时都要去找一次,实在是一件令人厌烦的事。基于GUI的操作系统就是计算机上的数据和功能的一个门面。每次点击、拖动和移动某个东西时,实际上是在跟一个门面打交道,间接地执行一些幕后的命名。
鉴于你可能已经有过一些javascript使用经验并且在网上找过适用于各种浏览事件监听器的方法,也许见过这样的代码:
function addEvent(el,type,fn){
if(window.addEventListener){
el.addEventListener(type,fn,false);
}else if(window.attachEvent){
el.attachEvent(“on”+type,fn);
}else{
el[“on”+type]=fn;
}
}
开发人员在浏览器中使用javascript的很大一部分原因就在于事件监听器。因为javascript是一种事件驱动的语言,如果javascipt应用程序中要是连一个事件监听器都没的话,是一件奇怪的事。不过这种事的确可能存在。在有些高级应用中,javascript只被用作一种输出文本和生成DOM节点的编程环境。即便如此,这种语言的力量在很大程序上还是来自于把动作和事件关联起来的能力。这是它很有用的一个方面。
addEvent函数是一个基本的门面,有了它,就有了一种为DOM节点添加事件监听器的简便方法,你不用再为每次为一个元素添加事件监听时都得针对浏览器间的差异进行检查而烦恼。有了这个便利方法,你大可把与添加事件监听器有关的各种低层细节抛在脑后,而把心思集中在如何构建自己的应用系统上。
javascript库是为人设计的,设计它们的目的在于节省时间、简化常见任务和提供为每个浏览都实现了的内置javascript函数更易于使用的接口。在大量使用DOM脚本编程浏览器环境中,的确需要有javascript库才能对付。如今的Web应用程序开发要求你必须尽量提高编程效率。要做到这一点,最简单的办法就是创建自己的工具函数集或使用Prototype/jQuery/YUI/DOJO这些第三方的javascript库
门面模式给予开发人员的另一个好处表现在对函数的组合上,这些组合而得的函数又叫便利函数。下面是一个纯粹形式化的例子:
function a(x){
//do stuff here
}
function b(y){
//do stuff here
}
function ab(y){
a(x);
b(y);
}
你可能会想为什么不一开头就把所有功能放到ab函数中去。答案是分别提供a、b和ab这几个函数可以获得更多粒度控制和灵活性。
以DOM脚本编程中经常用到的两个普通事件方法为例:
event.stopPropagation();
event.preventDefault();
因为不同的浏览器厂商为这两个功能提供的接口略有差异,所以现在摆在我们面前的就是一个用门面模式实现使得方法的理想方案
var DED =window.DED || {};
DED.util = {
stopPropagation:function(e){
if(e.stopPropagation){
e.stopPropagation();
}else{
e.cancelBuble = true;
}
},
preventDefault:function(e){
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
},
stopEvent:function(e){
DED.util.stopPropagation(e);
DED.util.preventDefault(e);
}
}
尽管看起来很像,但门面模式并不是适配器模式。适配器是一种包装器,用来对接口进行适配以便在不兼容系统中使用它。而创建门面元素则是图个方便。它并不用于达到与需要特定接口的客户系统打交道这个目的,而是用于提供一个简化的接口。
设置html元素的样式是DHTML的核心内容,也是其初衷。要设置HTML元素的样式,只要对样式对象特定属性赋值即可。通常,在这方面浏览器的差异问题基本上没有多大影响,也无关紧要。如:
var elem =document.getElementById(‘content’);
elem.style.color =‘red’;
elem.style.fontSize= ‘16px;
现在假设要一次设置几个元素的某个样式。这是一个合理的要求。如有三个ID分别为foo/bar/baz的元素,并想把它们的文本颜色都设置为红色,可以这样做:
var elem1 =document.getElementById(‘foo);
elem1.style.color= ‘red’;
var elem2 =document.getElementById(‘bar);
elem2.style.color= ‘red’;
var elem3 =document.getElementById(‘baz);
elem3.style.color= ‘red’;
像这样不停地写getElementById并且为每一个元素设置同样的属性和值有点乏味。门面模式可以在此派上用场。为了方便起见,我们这就着手创建一个接口,以简化成批设置一级元素的样式的工作。
先写出使用待设计的使得方法的代码,然后再编写这个方法本身:
setStyle([‘foo’, ‘bar’,‘baz’],’color’,’red’);
可以看出,要创建的函数名为setStyle,这里传递给它的第一个参数是一个包含着三个ID值的数组。第二个参数果设置的样式属性,而第三个参数则是该属性的值。了解接口后,我们现在可以给出一个具体的实现。下面的函数就是一个门面元素,它可以满足我们的需要
function setStyle(element,prop,val){
for(var i=0,len=element.length;i<len;i++){
document.getElementById(elements[i]).stype[prop]=val;
}
}
DED.util.Event={
getEvent:functon(e){
return e||window.evnet;
},
getTarget:functon(e){
return e.target||e.srcElement;
},
stopPropagation:function(e){
if(e.stopPropagation){
e.stopPropagation();
}else{
e.cancelBuble = true;
}
},
preventDefault:function(e){
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
},
stopEvent:function(e){
DED.util.stopPropagation(e);
DED.util.preventDefault(e);
}
}
转载地址:http://bgzxi.baihongyu.com/