外观模式说明
外观模式是用于由于子系统或程序组成较复杂而提供的一个高层界面接口,使用客户端更容易访问底层的程序或系统接口;
外观模式是我们经常使用遇到的模式,我们经常涉及到的功能,可能需要涉及到几个子接口或子系统,而我们的某个功能,可能只需要这向这多个子接口中的一个或几个组成的顺序封装。如果是业务功能直接对应子接口或子系统的,可能要求开发人员对内部需要相当的了解;你可能需要去了解业务流程是怎么走,他的顺序是什么,等等。这即需要开发员了解业务,也使得客户端编程变得相当的复杂;
这里如果有一层,或是一个类,专门提供好封装好我们要使用的方法,客户端功能只需要与这个中间层类交互,中间层类的相应方法由了解业务的相关开发人员组织封装,那么程序将变得非常的简单,程序员只需要知道他这个功能所需要对应方法是哪个即可,也不用知道内部的逻辑。这个中间层类就是我们说的外观类,这就是外观模式的思想。
外观模式作用
- 为子系统中的一组接口提供了一个高层接口
- 使用者使用这个高层接口
- 原来的系统中用户对接每一个子系统
- 使用外观模式之后用户只需要对接外观那个高层接口即可
使用场景
场景1:
var getName = function(){
return ”svenzeng”
}
var getSex = function(){
return ‘man'
}
如果你需要分别调用getName和getSex函数. 那可以用一个更高层的接口getUserInfo来调用.
var getUserInfo = function(){
var info = a() + b();
return info;
}
场景2:
对浏览器中绑定事件的实现
document.addEventListener('click', function(e) {
e.preventDefault();
console.log('click');
})
但在老版IE中(低于9)是没有addEventListener这个API的,低版本IE中绑定事件要这样做:
document.attachEvent('onclick', function(e) {
e.preventDefault();
console.log('click');
})
我们需要兼容一下两个不同平台的实现:
var addEvent = function (el, ev, fn) {
if (el.addEventListener) {
el.addEventListener(ev, fn, false);
} else if (el.attachEvent) {
el.attachEvent('on' + ev, fn);
} else {
el['on' + ev] = fn;
}
};
如上addEvent函数就是外观模式的一个经典实现,它磨平了不同平台绑定事件API不同的问题,让使用者直接调用addEvent方法即可,而不用在意兼容平台的问题。
jQuery中其实就有很多外观模式的应用,jQuery的经典之处很重要的一点就在于它使得开发者不用去在乎诸多的平台API上的区别。比如对于.css方法,.html()方法等都是外观模式的一种实现。
场景3:
好比一个公司,有好几个职能部门,老板哪一天需要各方面工作的执行情况了,他就跑去一个个部门内部,问个员工说这个某某事情办得怎么样了,如果问对人了能直接给老板答案,要是不是这个人负责的,他还会跟老板说,哦,这事是谁谁负责的,老板还得跑去问下那人,多麻烦。
如果每个职能部门设个主管负责人,老板直接去找它了解情况就可以了,老板也不用关心这个负责人是怎么知道这些的,他只要想了解的这么1,2,3件事情的情况跟进展即可。
现在按这个实例场景实现源码:
几个部门职能类:
部门1 (业务部门):
function BusinessDept() {
this.manager = '陈经理'; //负责人
}
BusinessDept.prototype = {
MonthSales: function() {
console.log(this.manager + '说:这个月销售额是xxx');
},
NextPlan: function() {
console.log(this.manager + '说:接下来的计划是这样的,xxxx');
}
}
部门2(研发部门):
function RDdept() {
this.manager = '黄经理';
}
RDdept.prototype = {
progress: function() {
console.log(this.manager + '说:目前的项目情况跟进展是这样的xxx');
},
deptPlan: function() {
console.log(this.manager + '说:接下来的部门规划是这样的xxx');
}
}
以上是各部门主管所要回答老板的问题;
接下来建立外观类,用于组织老板想问的问题;
function Facade() {
this.business = new BusinessDept() ;
this.rddept = new RDdept();
}
Facade.prototype = {
DeptSituation: function() {
this.business.MonthSales(); //销售部经理先说;
this.rddept.progress();
},
deptPlan: function() {
this.business.NextPlan(); //报告接下来计划;
this.rddept.deptPlan();
}
}
接下来老板把两位经理叫到面前,开始问话了:
var facade = new Facade();
console.log('老板问:现在介绍下自己部门的情况?');
facade.DeptSituation();
console.log('老板问:接下来有什么规划?');
facade.deptPlan();
总结
使用外观模式,可以使得接口或类之间解耦,使得类之间不必产生依赖,不必要使用时得A包含B,或是B一定得包含A,这违反了关闭修改原则,使用中间层外观类包装,可以使得接口调用变得简单,使用子接口或子系统对象调用变得更加自由可组织。
外观模式经常出现我们的编程中,外观模式经常使用在架构系统的模式定义中出现,我们的系统要使用第三方的接口服务,也经常再加层外观层用于组织可用的业务接口;