以jq为案例查看外观模式

前言

套餐服务–外观模式,属于大类结构型设计模式的一种,通常是为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口让使用者对子系统的接口更加容易访问。

在js中有时也会对底层结构兼容性做统一的封装来简化用户的使用。

备注:本文的案例以es5为主,部分会涉及jq的代码,大家理解思想就好。如果你有es6以及目前三大框架的实例应用案例,欢迎分享。

生活场景延伸

相信大家都经常下饭馆或者点外卖,一般情况下每个店面都会有自己的推荐套餐,这个套餐里配置了菜、汤、米饭等,在点了套餐时就不需要关注这个套餐下每个类的名字叫什么。

饭店的这种将几个不同品种的需求搭配在一起捆绑给顾客的方式就是套餐模式,和我们的外观模式是有共通之处的。

从点击事件说起—-兼容方式&&底层向上封装

相信古老的程序员都用过jq,还有jq的click事件,一般的写法是这样的对吧。

$(target).on(eventType,fn)

也相信大家都用过或者多少知道一点js的原生语法,绑定事件是如何写的。

let dom  = document.querySelector(target)
dom.addEventListener(type,fn,false)

发生jq的写法很亲民,很简洁有没有,把使用变的更加简洁了,另外一家是大家可能不知道的,其实addEventListener 并不是一个兼容的写法,其应该的兼容写法是这样的:

if(dom.addEventListener){
dom.addEventListener(type,fn,false)
} else if(dom.attachEvent) {
dom.attachEvent('on'+type,fn)
} else {
dom['on'+type] = fn 
}

是这样的么?我们找到jq的事件源码看一下吧 :源码文件位置(要到比较老的1.x的版本才会找到这部分针对事件写的兼容代码哦):https://github.com/jquery/jquery/blob/1.12.4/src/event.js

// event.add 方法中,183行开始
// Init the event handler queue if we're the first
if ( !( handlers = events[ type ] ) ) {
    handlers = events[ type ] = [];
    handlers.delegateCount = 0;
    // Only use addEventListener/attachEvent if the special events handler returns false
if ( !special.setup ||
                    special.setup.call( elem, data, namespaces, eventHandle ) === false ) {

// Bind the global event handler to the element
//use different ways to add event according to different support situation (Robin 批注)
                    if ( elem.addEventListener ) {
                        elem.addEventListener( type, eventHandle, false );

                    } else if ( elem.attachEvent ) {
                        elem.attachEvent( "on" + type, eventHandle );
                    }
                }
            }

结论:从上面可以看出一个简单的添加事件就用了外观模式,而实际上add事件本身在jq看来也是属于封装的底层,其通过再一次封装,将其封装到了on方法中。在整个jq的框架中,在兼容写法上、向上封装上不断地运用了外观模式来设计。

function on( elem, types, selector, data, fn, one ) {
//省略若干代码
return elem.each( function() {
        jQuery.event.add( this, types, fn, data, selector );
    } );
}

小型代码库

还是以刚才的jq库为例子,在完成on方法定义的时候,我们看到了一系列的套餐服务的设计暴露出来。每一个看似简单的服务或者套餐或者语法都是一个外观模式的最佳实践。

jQuery.fn.extend( {

    on: function( types, selector, data, fn ) {
        return on( this, types, selector, data, fn );
    },
    one: function( types, selector, data, fn ) {
        return on( this, types, selector, data, fn, 1 );
    },
...
})

更多

在新型的vue、react框架中也一定不缺少这样的例子,去找找看吧

参考文档

  • 张容铭《javascript设计模式》

发布者

Robinson Zhang

热爱前端,热爱分享,坚持高频写作,从小白到大师只是时间问题。