门面模式
前言
门面模式的本质是实现一个简单的同一接口来处理对各个子系统接口的处理和调用.和桥接模式不同的是:桥接模式中的各个类是全然独立的,桥接模式仅仅在必要的时候将这些类关联起来.
门面模式则有点不同.门面模式事实上能够非常形象的比作是一家咖啡店的店面窗体,客户仅仅须要说明自己是须要哪种咖啡,也就是说咖啡店提供给客户的仅仅是各类咖啡的选择接口,而将内部的各个子类行为封装起来,比方加水啊,拆包装啊啥的,咱也不懂,就瞎说呗,反正就是把制作咖啡的过程封装起来,不用你知道,仅仅把最后你想要的咖啡给你.
正文
门面模式的长处在于我们将客户与较为复杂的子系统方法和接口分离开来,减少用户与各个子系统间耦合度来提高代码指令.
看下图:
以下是一个纯粹形式化案例:
function a(x){ // do something } function b(y){ // do something } function ab( x, y ){ a(x); b(y); }
当然形式上与桥接模式有非常大程度上类似,以下的小样例能够感受下其和桥接模式不同
var N = window.N || {}; N.tools = { stopPropagation : function( e ){ if( e.stopPropagation ){ e.stopPropagation(); }else{ e.cancelBubble = true; } }, preventDefault : function( e ){ if( e.preventDefault ){ e.preventDefault(); }else{ e.returnValue = false; } }, stopEvent : function( e ){ N.tools.stopPropagation( e ); N.tools.preventDefault( e ); } }
一个小的阻止事件冒泡一级组织默认事件工具方法,从其代表性的stopEvent不难看出事实上质与桥接模式的差别.其上面两个方法stopPropagetion和preventDefault非常会令人认为类似于适配器模式,的确是非常类似于适配器模式,只是适配器模式的主要针对于将接口进行适配包装,时期适用于各种不同兼容性的环境.意思差点儿相同就是说,假设提供兼容性的信息使其方法在不同环境下生成不同的方法,比方一些匿名自调用函数依据推断返回不同函数的类似形式,而不是说每次执行再在函数内部进行推断执行,则称其为适配器模式更为适合一点.
对于门面模式的一大优点就是对函数的组合上,宛如上面纯粹模式的样例,门面模式形式的组合函数又称为便利函数,看案例:我们须要将id为content的div元素设置为文本颜色red,那么简单的代码:
var element = document.getElementById('content'); content.style.color = 'red'; //如还想设置字体大小为20px content.style.fontSize = '20px';
那么当一个元素须要设置多种属性时:
function setStyle(id,styles){ var element=document.getElementById(id); for(var key in styles){ if(styles.hasOwnProperty(key)){ element.style[key]=styles[key]; } } } setStyles('content',{ color:'red', fontSize:'20px'} );
setStyles就相当于一个便利函数,也能够视作门面元素,只是是相对于最简单的一类.
假设说是具有好几个元素,均须要设置同样的一批属性,那么将setStyles包装一下,将其嵌入在还有一个门面元素之中,组合成为一个结构相对复杂的门面模式实例:
function setCSS( ids, styles ){ for( var i = 0,len = ids.length; i<len; i++ ){ setStyles( ids[i], styles ); } }
从setCSS中能够看出,对于使用setCSS的用户来收,根本不知道其内部的setStyles代码形式.可想而知,当一块逻辑代码较为复杂,调用很多各个接口等的时候,我们使用门面模式将其封装,能够带来非常大的便利性.
总结
门面模式大致上能够分为两个小类,某块代码重复出现,比方函数a的调用基本都出如今函数b的调用之前(尽管基本上没有那么简单的形式),那么你能够考虑将这块代码使用门面演示样例包装起来,来优化结构.另一种即是对于一些浏览器不兼容的API,放置在门面模式内部进行推断,处理这些问题最好的方式便是将跨浏览器差异所有集中放置到一个门面模式实例中来提供一个对外接口.
当然也须要注意的是,对于门面模式的滥用所产生的后果也是非常严重的,不但使代码总体结构较为松散,还使代码可读性严重减少,寻找一处BUG可能须要从一个门面实例中找到还有一个,再联系到第三个第四个,会使代码的维护性较差.