什么是外观(Facade)模式

外观模式隐藏了底层的复杂性,为外部提供一个更高层次的接口,我们可以把它想像成简化的API来提供给使用者,使得外部更容易使用。

使用场景

外观模式 - 图1


  1. 为复杂的模块提供更易外界访问的封装(Facade)
  2. 内部模块间相互独立(ModuleA、ModuleB、ModuleC)
  3. User不与子模块单独交互

    外观模式示例

    1.跨浏览器的兼容方案

    在不同的浏览器中,对于DOM节点添加事件有不同的api,我们可以利用外观模式来创建一份通用的兼容方案。
  1. var addCrossBrowserEvent = function (el, ev, cb) {
  2. if (el.addEventListener) {
  3. el.addEventListener(ev, callback, false)
  4. } else if (el.attachEvent) { // ie 特有
  5. el.attachEvent("on" + ev, cb)
  6. } else {
  7. el["on" + ev] = fn
  8. }
  9. }

2.$.ajax的外观

在使用jquery的ajax时,我们除了直接使用$.ajax,我们还会如此使用:

  1. $.get(url, data, callback, dataType);
  2. $.post(url, data, callback, dataType);
  3. $.getJSON(url, data, callback);
  4. $.getScript(url, callback);

实际上这些方法都是对$.ajax做了进一步的封装

  1. // $.get()
  2. $.ajax({
  3. url: url,
  4. data: data,
  5. dataType: dataType
  6. }).done(callback)
  7. // $.post()
  8. $.ajax({
  9. type: "post",
  10. url: url,
  11. data: data,
  12. dataType: dataType
  13. }).done(callback)
  14. // $.getJSON()
  15. $.ajax({
  16. url: url,
  17. data: data,
  18. dataType: 'json'
  19. }).done(callback)
  20. // $.getScript()
  21. $.ajax({
  22. url: url,
  23. dataType: 'script'
  24. }).done(callback)

附:jquery里的选择器也是一个典型的Facade,内部会根据传入的选择器类型来判断需要调用内部的getById或是getbyClass等方法,而我们在使用时则无须关心这些内部方法。

外观模式的缺点

外观模式将复杂的库/子系统的调用做了适当的抽象,但同样也有一些缺点,其中比较值得注意的就是性能。我们需要明确提供给实现的抽象是否包含隐性成本,如果是,这种成本是否是合理的。我们在直接使用document.getElementById(‘elid’)的性能肯定要优于$(‘#elid’),但如果性能成本是在可接受的范围内,并且给我们带来了更多的简便,那么这样的抽象就是值得的。