【D1n910】第9章 套餐服务 —— 外观模式
正常操作,正常分析,大家好,我是D1n910。
今天继续来学习 《JavaScript 设计模式》的第三篇 结构型设计模式
这是一个连续的读书笔记,所以如果你之前的内容没有看的话,可以去看看。






这里再次感谢 《Javascript 设计模式》及其作者 张荣铭,专栏内容是在它的基础上生成的。
其实学到现在,会发现自己已经用到过这里面很多种设计模式了,这些都是上学上课、平时学习以及看之前大佬的代码耳濡目染的。

第三篇 结构型设计模式
结构型设计模式关注于如何将类或者对象组合成更大、更复杂的结构,以简化设计。
第 9 章 套餐服务 —— 外观模式
外观模式(Facade):
为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易。在 Javascript 中有时也会用于对底层结构兼容性做统一封装来简化用户使用。
对接口进行二次封装隐藏其复杂性,并简化其使用。有时候外观接口的封装接口方法不需要接口的具体实现,只需要按照接口使用规则调用即可。这也是对系统与客户之间的一种松散耦合。 使得系统与客户之间不回因结构的变化而互相影响。
用于场景:比如IE低版本可以使用的代码以及高版本可以使用的代码;Vue 里 nextTick 的封装……
9.1、添加一个点击事件(p68)
前端人A给页面的 document 绑定了 onclick 事件,这是 DOM0 级事件。
document.onclick = function(e) {
//前端人 A do something
e.preventDefault();
if (e.target !== document.getElementById('myinput')) {
//前端人 A do something
}
}
这里有一个显而易见的问题,就是后继的同事新添加同样的 DOM0 方法,会被覆盖。
// just like this
document.onclick = function(e) {
//前端人 B do something
}
考虑到解决这种问题,我们会想到可以用 DOM2 级事件处理程序提供的 addEventListener 来实现。
在用 addEventListener 来绑定事件的话,有一个问题就是,在老版本的 IE 浏览器(低于 9)是不支持 addEventListener 的,要用 attachEvent,然后再再次的浏览器,不支持 DOM2 级事件,我们还要考虑用回 DOM0。
9.2、兼容方式(p69)
这就像饭堂点菜一样,我们只需要和阿姨说我们要什么菜、饭,饭堂阿姨就可以自己去菜盆里、桌子上、抽屉里……然后综合成一盘餐给我们。
这里我们可以把上面的内容集中在一起写。
// 外观模式
function addEvent(dom, type, fn) {
// 对于支持 DOM2 级事件处理程序 addEventListener 方法的浏览器
if (dom.addEventListener) {
dom.addEventListener(type, fn, false);
// 对于不支持 addEventListener 方法但支持 attachEvent 方法的浏览器
} else if (dom.attachEvent) {
dom.attachEvent('on' + type, fn);
} else {
dom['on'+ type] = fn
}
}
这样我们就可以很放心方便地进行事件绑定了。
addEvent(document, 'click', () => {alert('ddd')})
// 绑定第二个事件
addEvent(document, 'click', () => {alert('ddd2')})
9.3、除此之外(p70)
刚刚前端人 A 这边还有可以补充内容的地方,再看看代码内容:
document.onclick = function(e) {
//前端人 A do something
e.preventDefault();
if (e.target !== document.getElementById('myinput')) {
//前端人 A do something
}
}
再看看代码,我们知道 IE 低版本浏览器不兼容 e.preventDefault() 和 e.target,所以又可以写下面的外观模式:
// 获取事件对象
var getEvent = function(event) {
// 有 event 的时候返回 event,否则 window.event(IE)
return even || window.event;
}
// 获取元素
var getTarget = fucntion (event) {
var event = getEvent(event);
return event.target || event.srcElement;
}
// 阻止默认行为
var perventDefault = function (event) {
var event = getEvent(event)
if (event.perventDefault) {
event.perventDefault();
} else {
event.returnValue = false;
}
}
我们原来的函数就可以改成下面这样
addEvent(document, 'click', function(event) {
preventDefault(event);
if (getTarget(event) !== document.getElementById('myinput')) {
//前端人 A do something
}
})
9.4、小型代码库(p70)
根据之前学的单例模式,我们很容易吧上面的东西集合到小型代码库里,这样就不会直接暴露到页面全局对象了。
本章 End,学习进度 9/40,加油加油
D1n910 于2021年02月19日 12:53 在福永