Facade Pattern
外观模式的实现与应用场景
问题
什么是外观模式?在前端开发中如何应用?
解答
外观模式为复杂的子系统提供一个简化的统一接口,隐藏内部复杂性。
基本实现
// 复杂的子系统
class CPU {
freeze() {
console.log('CPU 冻结')
}
jump(position) {
console.log(`CPU 跳转到 ${position}`)
}
execute() {
console.log('CPU 执行')
}
}
class Memory {
load(position, data) {
console.log(`内存加载 ${data} 到 ${position}`)
}
}
class HardDrive {
read(sector, size) {
console.log(`硬盘读取扇区 ${sector},大小 ${size}`)
return 'boot data'
}
}
// 外观类 - 提供简化接口
class ComputerFacade {
constructor() {
this.cpu = new CPU()
this.memory = new Memory()
this.hardDrive = new HardDrive()
}
// 一键启动,隐藏复杂的启动流程
start() {
this.cpu.freeze()
this.memory.load(0, this.hardDrive.read(0, 1024))
this.cpu.jump(0)
this.cpu.execute()
}
}
// 使用
const computer = new ComputerFacade()
computer.start() // 一行代码完成复杂操作
前端实际应用:封装 HTTP 请求
// 复杂的底层实现
class RequestInterceptor {
process(config) {
config.headers = config.headers || {}
config.headers['Authorization'] = `Bearer ${localStorage.getItem('token')}`
return config
}
}
class ResponseHandler {
handle(response) {
if (response.code !== 200) {
throw new Error(response.message)
}
return response.data
}
}
class ErrorLogger {
log(error) {
console.error('请求错误:', error)
// 上报错误监控系统
}
}
// 外观类
class HttpFacade {
constructor() {
this.interceptor = new RequestInterceptor()
this.handler = new ResponseHandler()
this.logger = new ErrorLogger()
}
async request(url, options = {}) {
try {
// 请求拦截
const config = this.interceptor.process({
url,
method: 'GET',
...options
})
// 发送请求
const res = await fetch(config.url, config)
const json = await res.json()
// 响应处理
return this.handler.handle(json)
} catch (error) {
this.logger.log(error)
throw error
}
}
// 简化的 API
get(url) {
return this.request(url)
}
post(url, data) {
return this.request(url, {
method: 'POST',
body: JSON.stringify(data)
})
}
}
// 使用 - 调用者无需关心内部细节
const http = new HttpFacade()
http.get('/api/users')
http.post('/api/login', { username: 'admin', password: '123' })
浏览器兼容性封装
// 事件处理的外观模式
const EventFacade = {
addEvent(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false)
} else if (element.attachEvent) {
// IE8 及以下
element.attachEvent('on' + type, handler)
} else {
element['on' + type] = handler
}
},
removeEvent(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false)
} else if (element.detachEvent) {
element.detachEvent('on' + type, handler)
} else {
element['on' + type] = null
}
}
}
// 使用 - 无需关心浏览器差异
EventFacade.addEvent(document.getElementById('btn'), 'click', () => {
console.log('clicked')
})
关键点
- 简化接口:将复杂子系统的多个接口合并为一个简单接口
- 解耦:客户端与子系统之间通过外观类通信,降低耦合度
- 不限制访问:外观模式不阻止直接使用子系统,只是提供便捷入口
- 典型应用:jQuery(DOM 操作)、axios(HTTP 请求)、Lodash(工具函数)
- 适用场景:为复杂模块提供简单 API、封装浏览器兼容性、统一第三方库调用
目录