设计模式
在 JS 中,很多设计模式都是通过闭包和高阶函数实现的。和传统语言的实现不太一样。
前置知识
闭包
高阶函数
满足任一条件
- 函数作为参数传递
- 函数作为返回值返回
面向对象的 JavaScript
- 动态类型和鸭子类型
- 多态
- 封装
- 原型模式和基于原型继承的 JavaScript 对象系统
AOP
面向切面的编程
- 把一些根核心业务无关的功能抽离出来,包括日志统计、安全控制、异常处理等。
单例模式
单例模式的核心就是确保只有一个实例,并提供给全局访问
var a = {} 就是一个单例模式
不过它暴露了全局变量
使用闭包封装私有变量
var user = (function() {
var __name = 'seven'
return {
getName() {
return __name
}
}
})()
通用的惰性单例
在需要的时候才创建对象实例
var getSingle = function(fn) {
var ret
return function() {
return ret || ret = fn.apply( this, arguments)
}
}
观察者模式(发布-订阅)
你在 DOM 节点上绑定过事件函数,你就是用过发布-订阅模式
// 随意添加或者删除订阅者
document.body.addEventListener('click', function() { alert(2) },false)
document.body.addEventListener('click', function() { alert(2) },false)
document.body.click()
ES6 实现
class Subject() {
constuctor() {
this.observers = []
}
add(observer) {
this.observers.push(observer)
}
remove(observer) {
const index = this.observers.indexOf(observer)
if (index > -1) {
this.observers.splice(index, 1)
}
}
trigger() {
this.observer.forEach(observer => {
observer.update()
})
}
}
class Observer() {}
constuctor(name) {
this.name = name
}
update() {
console.log(this.name)
}
工厂模式
迭代器模式
迭代器就是循环访问聚合对象中的每个元素
所有的集合类型、字符串都有默认迭代器
- keys()
- values()
- entries()
代理模式
缓存代理
缓存代理可以为一下开销大的运行结果提供暂时的存储, 下次如果参数一样,返回前面存储的运算结果。
// 求乘积的函数
var mult = function() {
var a = 1
for (var i = 0; l = arguments.length; i < 1; i++) {
a *= arguments[i]
}
return a
}
var proxyMult = (function() {
var cache = {}
return function() {
var args = [].join.call(arguments, ',')
if (args in cache) {
return cache[ args ]
}
return cache[args] = mult.apply(this, arguments)
}
})()
proxyMult(1, 2, 3, 4)
适配器模式 Adapter
解决两个软件实体间的接口不兼容的问题
var googleMap = {
show() {
}
}
var baiduMap = {
render() {
}
}
var renderMap = function( map ) {
if ( map.show instanceof Function) {
map.show()
}
}
var baiduMapAdapter = {
show() {
return baiduMap.render()
}
}
renderMap( googleMap )
renderMap( baiduMapAdapter )