一、前言

  门面模式,也称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. JDBCTemplate基础学习

    JDBCTemplate:spring提供的用于操作数据库的模板,类似DbUtils.使用时必须设置数据源(DataSource):数据源如DBCP.C3P0等 一.JDBCAPI简单使用Demo 1 ...

  2. Protocol Buffer技术详解(C++实例)

    Protocol Buffer技术详解(C++实例) 这篇Blog仍然是以Google的官方文档为主线,代码实例则完全取自于我们正在开发的一个Demo项目,通过前一段时间的尝试,感觉这种结合的方式比较 ...

  3. php-fpm.conf两个至关重要的参数

    这里规定了PHP-CGI的连接.发送和读取的时间,300秒足够用了,因此我的服务器很少出现504 Gateway Time-out这个错误.最关键的是php-fpm.conf的设置,这个会直接导致50 ...

  4. WPF 窗体拖转时不触发MouseLeftButtonUpEvent

    解决方案:手动添加Handler,因为e.Handled这个属性是用在路由事件中的,当某个控件得到一个RoutedEvent,就会检测Handled是否为true,为true则忽略该事件. //手动注 ...

  5. centos安装软件Error: Cannot find a valid baseurl for repo: base

    今天使用yum安装软件,出现下面的提示: Loaded plugins: fastestmirror, refresh-packagekit, securityLoading mirror speed ...

  6. 浏览器兼容性小整理和一些js小问题(后面会继续更新)

    最近在啃jQuery的源码,估计会啃到很多浏览器兼容性的问题,所以整理一下 1,IE下的内存泄露. 在IE中不在DOM树中的独立节点有javascript变量引用它的时候不会被回收. 解决:手动将该j ...

  7. Jquery validate插件使用方法详解

    html: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Reg.aspx.c ...

  8. Spark-1.0.0 standalone分布式安装教程

    Spark目前支持多种分布式部署方式:一.Standalone Deploy Mode:二Amazon EC2.:三.Apache Mesos:四.Hadoop YARN.第一种方式是单独部署,不需要 ...

  9. window.document

    <title>无标题文档</title> </head> <body>例1:<br />今年是哪一年?<input type=&quo ...

  10. 微信5.4你所不知道的事 X5浏览引擎提速50%-80%

    微信5.4新增包括搜索公众号.识别图中二维码.面对面收钱等功能,但是你可知道新版微信X5浏览引擎提速了,提升50%-80%的网络传输速度及相同比例流量节省? 从X5浏览引擎开发人员得知,X5浏览技术基 ...