一、前言

  门面模式,也称Facade(外观)模式。核心的两点作用——

  1> 简化类的接口(让接口变得更加容易理解、容易应用、更加符合对应业务),来掩盖一个非常不同或者复杂的实现

  2> 消除类与使用它的客户代码之间的耦合

  可以把门面模式想成是简化API来展示给其他开发人员,通常都是可以提高可用性。

二、举例

  例子一、事件监听

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;
}
}

  有了这个门面,就有了一种为DOM节点添加事件监听器的简便方法,就不必再为每次为一个元素添加事件监听器都得针对浏览器间的差异进行检查而烦恼。

  

  例子二、组合函数

function a(x) {
// do stuff here...
}
function b(y) {
// do stuff here...
}
function ab(x, y) {
a(x);
b(y);
}

  分别提供a、b和ab这几个函数可以获得更多粒度控制和灵活性。

  

  例子三、工具函数

  在处理跨浏览器的开发问题时,最好创建一些门面函数。如果涉及一个大型库,那么最好把其中所有的工具元素聚拢在一起,这样更好用,访问起来也更方便。鉴于各种浏览器在事件处理表现出来的大量差异,开发一个事件工具很有必要。

var DED = window.DED || {};
DED.util.Event = {
getEvent: function(e) {
return e || window.event;
},
getTarget: function(e) {
return e.target || e.srcElement;
},
stopPropagation: function(e) {
if (e.stopPropagation) {
// W3 interface
e.stopPropagation();
} else {
// IE interface
e.cancelable();
}
},
preventDefault: function(e) {
if (e.preventDefault) {
// W3 interface
e.preventDefault();
} else {
// IE interface
e.returnValue = false;
}
},
stopEvent: function(e) {
DED.util.stopPropagation(e);
DED.util.preventDefault(e);
}
};

  应用上面的例子

addEvent($('#emample'), 'click', function(e) {
// who clicked me
console.log(DED.util.Event.getTarget(e));
// stop propagation and prevent the default action
DED.util.Event.stopEvent(e);
});

  

  例子四、结合其他模式一起应用

  门面模式不是必须单独使用。他们也可以与其他模式集成,如Module模式。Module模式的实例包含很多已经定义的私有方法。然后使用门面模式提供一个简单的API来访问这些方法。

var module = (function() {
var _private = {
i: 5,
get: function() {
console.log('current value:' + this.i);
},
set: function(val) {
this.i = val;
},
run: function() {
console.log('running...');
},
jump: function() {
console.log('jumping...');
}
}; return {
facade: function(args) {
_private.set(args.val);
_private.get();
if (args.run) {
_private.run();
}
}
};
}());

三、适用场景

  1.判断是否应该应用门面模式的关键在于辨认那些反复成组出现的代码。如果函数b出现在函数a之后这种情况经常出现,那么也许你应该考虑添加一个把这两个函数组合起来的门面函数。

  2.在核心工具代码中加入门面函数的另一个目的是应对js内置函数在不同浏览器中的不同表现。这样做并不是因为不能直接使用这些API,而是因为在处理跨浏览器的差异问题时最好的解决方法就是把这些差异抽取到门面方法中。它们可以提供一个更一致的接口。

四、优势

  1.门面模式的目的就是让程序员过得更轻松一些。编写一次组合代码,然后就可以反复使用它,这有助于节省时间和精力。它们可以替你把硬骨头啃掉,并且提供了一个处理常见问题和任务的简化接口。
  2.门面方法方便了开发人员,并且提供了较高层的功能,如果不用门面模式的话,这些功能实现起来可能会乏味而又费力。
  3.它们还能降低对外部代码的依赖程度,这为应用系统的开发增加了一些额外的灵活性。通过使用门面模式,可以避免与下层子系统紧密耦合。这样可以对这个系统进行修改而不会影响到客户代码。

五、劣势

  有时候门面元素也会带来一些不必要的额外负担。方便的东西不一定就得用。门面模式常常被滥用。有时相比一个庞杂的门面函数,其组成函数在粒度方面更有吸引力。这是因为门面函数可能常常会执行一些你并不需要的任务。

六、结论

  门面模式可用来创建便利函数,这些函数为执行各种复杂任务提供了一个简单的接口。它们使代码更容易维护和理解。它们还能弱化子系统和客户代码的耦合。便利方法有助于简化常见的重复性任务,以及把经常相伴出现的常用函数组合在一起。这个模式在DOM脚本编程这种需要面对各种不一致 的浏览器接口的环境中很常用。但是要注意,当使用门面模式的时候,要试着了解涉及的任何性能成本,并确认是否值得抽象。

源自:JavaScript设计模式(人民邮电出版社)——第十章,门面模式

参考:《JavaScript设计模式》 —— 9.9 Facade(外观)模式

【读书笔记】读《JavaScript设计模式》之门面模式的更多相关文章

  1. 读书笔记之 - javascript 设计模式 - 享元模式

    本章探讨另一种优化模式-享元模式,它最适合于解决因创建大量类似对象而累及性能的问题.这种模式在javascript中尤其有用,因为复杂的javascript代码很快就会用光浏览器的所有可用内存,通过把 ...

  2. 读书笔记之 - javascript 设计模式 - 责任链模式

    责任链模式可以用来消除请求的发送者和接收者之间的耦合.这是通过实现一个由隐式地对请求进行处理的对象组成的链而做到的.链中的每个对象可以处理请求,也可以将其传给下一个对象. 责任链的结构: 责任链由多个 ...

  3. 读书笔记之 - javascript 设计模式 - 装饰者模式

    本章讨论的是一种为对象增添特性的技术,它并不使用创建新子类这种手段. 装饰者模式可以透明地把对象包装在具有同样接口的另一对象之中,这样一来,你可以给一些方法添加一些行为,然后将方法调用传递给原始对象. ...

  4. 读书笔记之 - javascript 设计模式 - 门面模式

    门面模式有俩个作用: 简化类的接口 消除类与使用它的客户代码之间的耦合 在javascript中,门面模式常常是开发人员最亲密的朋友.它是几乎所有javascript库的核心原则,门面模式可以使库提供 ...

  5. 读书笔记之 - javascript 设计模式 - 代理模式

    代理(proxy)是一个对象,它可以用来控制对另一对象的访问.它与另外那个对象实现了同样的接口,并且会把任何方法调用传递给那个对象.另外那个对象通常称为本体.代理可以代替本体被实例化,并使其可被远程访 ...

  6. 再起航,我的学习笔记之JavaScript设计模式08(建造者模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...

  7. 再起航,我的学习笔记之JavaScript设计模式09(原型模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...

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

    经过一段时间的学习与分享,我们对创建型设计模式已经有了一定的认识,未来的一段时间里我们将展开新的篇章,开始迈入结构性设计模式的学习. 结构性设计模式与创建型设计模式不同,结构性设计模式更偏向于关注如何 ...

  9. 再起航,我的学习笔记之JavaScript设计模式14(桥接模式)

    桥接模式 桥接模式(Bridge): 在系统沿着多个维度变化的同时,又不增加其复杂度并已达到解耦 从定义上看桥接模式的定义十分难以理解,那么我们来通过示例来演示什么是桥接模式. 现在我们需要做一个导航 ...

  10. 再起航,我的学习笔记之JavaScript设计模式15(组合模式)

    组合模式 组合模式(Composite): 又称部分-整体模式,将对象组合成树形结构以表示"部分整体"的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 如果有一个 ...

随机推荐

  1. KPROCESS IDT PEB Ldr 《寒江独钓》内核学习笔记(3)

    继续上一篇(2)未完成的研究,我们接下来学习 KPROCESS这个数据结构. 1. 相关阅读材料 <深入理解计算机系统(原书第2版)> 二. KPROCESS KPROCESS,也叫内核进 ...

  2. webkit模块介绍

    一.Webkit模块   用到的第三方库如下:   cairo 一个2D绘图库 casqt Unicode处理用的库,从QT中抽取部分代码形成的 expat 一个XML SAX解析器的库 freety ...

  3. view视图文件中的input等输入框必须含有name属性,不然控制器里的动作formCollection是没有值的

    view视图文件中的input等输入框必须含有name属性,不然控制器里的动作formCollection是没有值的,就是没有name属性,后台获取不到值

  4. hibernate criteria中Restrictions的用法

    方法说明 方法 说明 Restrictions.eq = Restrictions.allEq 利用Map来进行多个等于的限制 Restrictions.gt > Restrictions.ge ...

  5. ASP.NET WebForm中用async/await实现异步出人意料的简单

    1. 在.aspx中添加异步标记 <%@ Page Language="C#" Async="true"%> 2. 在.aspx.cs或者.ascx ...

  6. sudo: unable to resolve host ubuntu提示的解决

    http://blog.sina.com.cn/s/blog_6c9d65a1010180mg.html

  7. AngularJS--学习笔记(一)

    AngularJS官方网站提供了一个用于学习的示例项目:PhoneCat.这是一个Web应用,用户可以浏览一些Android手机,了解它们的详细信息,并进行搜索和排序操作. 对于PhoneCat项目的 ...

  8. php设置cookie,在js中如何获取

    在php中设置cookie. $email="abc@163.com"; setcookie("y_email",$email,time()+3600,&quo ...

  9. Matlab图像处理入门

    1. Matlab基础 1.1     数据格式 Matlab默认的数据格式为双精度浮点数的矩阵或数组,同时支持其它数据类型.Matlab将单变量看作1´1的数组.Matlab支持的数据类型如下: 索 ...

  10. NOIP2012 借教室

    描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样.面对海量租借教室的信息,我们自然希望编 ...