什么是外观(Facade)模式
外观模式隐藏了底层的复杂性,为外部提供一个更高层次的接口,我们可以把它想像成简化的API来提供给使用者,使得外部更容易使用。
使用场景
- 为复杂的模块提供更易外界访问的封装(Facade)
- 内部模块间相互独立(ModuleA、ModuleB、ModuleC)
- User不与子模块单独交互
外观模式示例
1.跨浏览器的兼容方案
在不同的浏览器中,对于DOM节点添加事件有不同的api,我们可以利用外观模式来创建一份通用的兼容方案。
var addCrossBrowserEvent = function (el, ev, cb) {
if (el.addEventListener) {
el.addEventListener(ev, callback, false)
} else if (el.attachEvent) { // ie 特有
el.attachEvent("on" + ev, cb)
} else {
el["on" + ev] = fn
}
}
2.$.ajax的外观
在使用jquery的ajax时,我们除了直接使用$.ajax,我们还会如此使用:
$.get(url, data, callback, dataType);
$.post(url, data, callback, dataType);
$.getJSON(url, data, callback);
$.getScript(url, callback);
实际上这些方法都是对$.ajax做了进一步的封装
// $.get()
$.ajax({
url: url,
data: data,
dataType: dataType
}).done(callback)
// $.post()
$.ajax({
type: "post",
url: url,
data: data,
dataType: dataType
}).done(callback)
// $.getJSON()
$.ajax({
url: url,
data: data,
dataType: 'json'
}).done(callback)
// $.getScript()
$.ajax({
url: url,
dataType: 'script'
}).done(callback)
附:jquery里的选择器也是一个典型的Facade,内部会根据传入的选择器类型来判断需要调用内部的getById或是getbyClass等方法,而我们在使用时则无须关心这些内部方法。
外观模式的缺点
外观模式将复杂的库/子系统的调用做了适当的抽象,但同样也有一些缺点,其中比较值得注意的就是性能。我们需要明确提供给实现的抽象是否包含隐性成本,如果是,这种成本是否是合理的。我们在直接使用document.getElementById(‘elid’)的性能肯定要优于$(‘#elid’),但如果性能成本是在可接受的范围内,并且给我们带来了更多的简便,那么这样的抽象就是值得的。