设计模式
单例模式
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点
实现方法
判断实例是否存在,存在则直接返回,不存在就创建再返回,确保一个类只有一个实例对象
场景: 登录的弹窗,elementui 的messge-box组件
惰性单例
创建对象和管理单例模式的职责被分布在两个不同的方法中,组合起来才具有单例模式的威力
创建对象,即业务逻辑;管理单例模式,即如何来创建并管理实例
管理单例模式代码
// 管理单例模式
var getSingle = function(fn) {
var result
return function () {
return result || (result = fn.apply(this, arguments))
}
}
var createLoginLayer = function () {
var login = document.createElement('div')
login.innerHTML = 'login'
div.style.display = 'none'
return div
}
var createSingleLogin = getSingle(createLoginLayer)
// 每次点击只创建一个登陆窗口单例
document.getElementById('btn').onclick = function () {
var loginDiv = createSingleLogin()
loginDiv.style.display = 'block'
}
getSingle函数接收的是fn,所以可以在其他场景继续使用管理单例模式的函数
比如继续创建单一的iframe或者消息弹框的方法
策略模式
定义:定义一系列的短发,把他们一个个封装起来,并且使他们可以相互替换
将算法的使用和算法的实现分离开
比如在对象中定义不同的属性对应不同的策略,在使用时通过传入访问对象的的属性拿到该策略来进行调用
var state = {
'a': function () { return 'a'},
'b': function () { return 'b' }
}
var calcFn = function (level) {
return state[level]
}
console.log(calcFn('a'))
表单验证规则分离
把校验的规则封装在策略对象中,这是算法的实现
在算法的使用中, 拿出策略对象中需要的规则,然后进行后面的逻辑处理
代理模式
定义:是为一个对象提供一个代用品或者占位符,以便控制对它的访问
虚拟代理实现图片预加载
var myImage = (function () {
var imgNode = document.createElement('img')
document.boyd.appendChild(imgNode)
return {
setSrc: function (src) {
imgNOde.src = src
}
}
})()
var proxyImg = (function () {
var img = new Image
img.onload = function () {
myImage.src = this.src
}
return {
setSrc: function (src) {
myImage.setSrc('http://aaa.gif')
img.src = src
}
}
})()
proxyImg.setSrc('http://eeee.png')
缓存代理
可以为一些开销大的运算结果提供暂时的存储,在下次运算时,如果传递的参数与之前的一致,则可以直接返回存储的运算结果
var mult = function () {
var a = 1
for (var i = 0; l = arguments.lengt; i < l; i++) {
a = a * arguments[i]
}
return a
}
var proxyMult = (function () {
var cache = {}
return function () {
var args = Array.prototype.join.call(arguments, ',')
if (args in cache) {
return cache[args]
}
return cache[args] = mult.apply(this, arguments)
}
})()
proxyMult(1,,2,3)
proxyMult(1,,2,3)
mult函数只专注自身的职责,而缓存功能是由代理对象实现的,体现了单一职责原则
函数的防抖节流也是代理模式的应用
装饰者模式
定义: 在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责
应用:react 高阶组件,react-redux中的@connect
用AOP装饰函数
数据统计上报
Function.prototype.before = function (beforeFn) {
var self = this
return function () {
beforeFn.apply(this, arguments)
return self.apply(this, arguments)
}
}
Function.prototype.after = function (afterFn) {
var self = this
return function () {
var ret = after.apply(this, arguments)
self.apply(this, arguments)
return ret
}
}
var showLogin = function () {
console.log('login')
}
var log = function () {
console.log('上报')
}
showLogin = showLogin.after(log)