# 设计模式——外观设计模式
上面的创建型设计模式,专注于创建对象。而结构性设计模式则专注于结构设计,通俗点来说就是对象与对象之间的结构设计,也就是如何将类或者对象进行更好的组织,以方便使用。
# 外观设计模式定义:
为一组复杂的子接口提供一个更高级的统一接口,以便更方便的去实现子接口的功能。看定义总是感觉很复杂,我们根据一些场景来具体分析:
HTML代码
<div id="btn1">按钮1</div>
<div id="btn2">按钮2</div>
js代码
let oBtn1= document.getElementById('btn1');
let oBtn2= document.getElementById('btn2');
//按钮1
function btn1Fn(){
console.log('这里是按钮1的内容')
}
//DOM事件的兼容性处理
if( document.addEventListener ){
oBtn1.addEventListener("click" , btn1Fn, false);
}else if(document.attachEvent){
oBtn1.attachEvent("onclick" , btn1Fn);
}else{
oBtn1.onclick = btn1Fn;
}
//按钮2
function btn2Fn(){
console.log('这里是按钮2的内容')
}
//DOM事件的兼容性处理
if( document.addEventListener ){
oBtn1.addEventListener("click" , btn2Fn, false);
}else if(document.attachEvent){
oBtn1.attachEvent("onclick" , btn2Fn);
}else{
oBtn1.onclick = btn2Fn;
}
上面代码中由两个按钮,每个按钮有对应的点击事件。但是我们知道如果直接使用onclickDOM0
级点击事件,那么就可能出现后续的事件覆盖前面的。因此建议使用DOM2级点击事件,但是addEventListener
存在兼容性问题,在IE
中存在不兼容。因此我们需要对每次事件做兼容性处理。从上面的代码中,我们可以看出,我们对按钮1和按钮2都做了兼容性处理。事实上,这些兼容性处理都是相同的,如果每一次都去写复杂的重复的兼容性代码,是没有意义的。因此,我们通常会将兼容性处理封装起来,作为一个统一的接口,在需要的时候,直接调用这个接口,而不是再去重复写这个复杂的兼容代码,这种将复杂的代码封装起来,其实就是外观设计模式. 我们看使用外观设计模式实现的代码:
let oBtn1= document.getElementById('btn1');
let oBtn2= document.getElementById('btn2');
//按钮1
function btn1Fn(){
console.log('这里是按钮1的内容')
}
//按钮2
function btn2Fn(){
console.log('这里是按钮2的内容')
}
function bindEvent(element,type,fn) {
if(document.addEventListener){
element.addEventListener(type,fn,false)
}else if(document.attachEvent){
element.attachEvent('on'+type,fn)
}else{
element["on"+type] = fn;
}
}
bindEvent(oBtn1,'click',btn1Fn)
bindEvent(oBtn2,'click',btn2Fn)
从上面的代码中,我们可以看到使用了bindEvent
来封装兼容性处理,然后oBtn1
和oBtn2
触发点击事件都是直接调用这个封装函数。其实这就是外观模式的一次典型应用。所有的API的兼容性封装其实都是外观模式的应用。外观模式其实就是把一些复杂的操作隐藏起来,然后我们从更高级别直接调用。我们再看我们在开发中经常使用到的一个例子:
var person = {
init:function(){
// 这里是初始化代码
},
getAge:function(){
// 这里是获取元素的方法
},
getName:function(){
// 这里是获取样式的代码
},
getJob:function(){
//这里是获取个人工作的代码
}
}
var name = person.getName();
上面的代码是一个对象person
,里面封装了与个人信息相关的age
,name
,job
等方法,然后在需要获取这些信息时,我们使用person.xx
来调用。其实这就是外观模式的另外一种应用。在开发中,我们经常会使用命名空间,将一些相关的信息都封装到这个对象中,这种将各类操作饥饿和在一起,对外提供统一的接口就是外观模式的典型应用。
# 外观设计模式总结:
外观设计模式时结构性设计模式,我们之前说过结构型设计模式是用于组织代码结构的。而外观设计模式就是把所有的子类饥饿和在一起,对外提供统一的接口这样的一种组织形式。 典型的使用就是各种兼容性API的封装和命名空间的使用。