外观模式
外观模式(Facade)为子系统中的一组接口提供了一个一致的界面,此模块定义了一个高层接口,这个接口使得这一子系统更加容易使用
外观模式不仅简化类中的接口,而且对接口与调用者也进行了解耦,外观模式经常被认为开发者必备,它可以将一些复杂操作封装起来,并创建一个简单的接口用于调用
简单说来就是你去餐厅吃饭,只需要和服务员前台沟通开个单子要吃什么即可订餐,而非自己去餐厅厨房做饭或亲自和厨师订餐,也不需要关心原材料和生产过程
外观模式的作用
- 在设计初期,应该要有意识地将不同的两个层分离,比如经典的MVC三层结构
- 每一层之间是独立的,各自负责自己的业务
- 当需要通信的时候,只需要调用相应的接口即可通信
- 在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观模式可以提供一个简单的接口,减少他们之间的依赖
- 在维护阶段为系统开发一个外观类,为设计粗糙和高度复杂的遗留代码提供比较清晰的接口,让新系统和外观对象交互
外观模式的注意事项
- 外观模式被开发者连续使用时会产生一定的性能问题,因为在每次调用时都要检测功能的可用性
- 这个性能问题体现在
- 当你要吃饭的时候,你不能够直接通过餐厅厨房获取食物
- 而是需要通过前台->服务员->厨师->服务员这样的流程获取食物
- 中间任何一环出了问题都无法吃上饭
外观模式示例
1 ) js底层的外观模式
- 在js中通过Object封装的任何类型的对象,如Function都是一种外观模式的使用
2 ) 模拟餐厅的外观模式举例
// 商店对象
var shop = {};
// 商店内制造食物
shop.createFood = function() {
console.log('Food ok');
return '米饭';
}
// 商店内制造饮料
shop.createDrink = function () {
console.log('Drink ok');
return '可乐';
}
// 商店内提供服务,封装了过程和细节
shop.service = function () {
// 提供食物和饮料
return this.createFood() + ' / ' + this.createDrink();
}
// 调用门面(外观)
var s = shop.service();
console.log(s);
3 ) 点击事件处理的外观模式举例
<button id='a'>A</button>
<script>
// 封装点击事件的冒泡处理
var stopEvent = function(e) {
e.stopPropagation();
e.preventDefault();
console.log('event handled');
};
document.getElementById('a').onclick = function(e) {
stopEvent(e); // 封装后,直接调用即可
}
</script>