(1)单例模式
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
实现方法:先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。
适用场景:一个单一对象。比如:弹窗,无论点击多少次,弹窗只应该被创建一次。
(2)发布/订阅模式
定义:又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
场景:订阅感兴趣的专栏和公众号。
(3)策略模式
定义:将一个个算法(解决方案)封装在一个个策略类中。
优点:
- 策略模式可以避免代码中的多重判断条件。
- 策略模式很好的体现了开放-封闭原则,将一个个算法(解决方案)封装在一个个策略类中。便于切换,理解,扩展。
- 策略中的各种算法可以重复利用在系统的各个地方,避免复制粘贴。
- 策略模式在程序中或多或少的增加了策略类。但比堆砌在业务逻辑中要清晰明了。
- 违反最少知识原则,必须要了解各种策略类,才能更好的在业务中应用。
应用场景:根据不同的员工绩效计算不同的奖金;表单验证中的多种校验规则,超市促销活动。
(4)代理模式
定义:为一个对象提供一个代用品或占位符,以便控制对它的访问。
好处:对外部提供统一的接口方法,让代理类在接口中实现对真实类的附加操作行为,从而可以在不影响到外部调用的情况下进行系统扩展
应用场景:
1.图片预加载
当我们的图片很大时,加载出来前会显示空白,这样对用户交互很不友好,我们可以先通过一张loading图占位,然后通过异步的方式加载图片,等图片加载好了再把完成的图片加载到img标签里面。
//只负责创建Img
var myImage = (function () {
var imgNode = document.createElement('img');
document.body.appendChild(imgNode);
return {
setSrc(src) {
imgNode.src = src;
}
}
})();
var proxyImage = (function () {
var img = new Image();
img.onload = function () {
myImage.setSrc(this.src);
}
return {
setSrc(src) {
myImage.setSrc(loading_img);
img.src = src;
}
}
})();
分类:
缓存代理:
第一次运行时候进行缓存,当下一次再运行相同时,直接从缓存中读取,避免重复一次运算功能;
比如:复杂的运算过程
虚拟代理:
合并HTTP请求,当短时间内有频繁的多次请求,我们可以利用虚拟代理搁置请求,等到合适的时机再执行
比如:函数防抖与节流
//模拟一段ajax请求
function ajax(content) {
console.log('ajax request ' + content)
}
//防抖
function debounce(fun, delay) {
return function (args) {
let that = this
let _args = args
clearTimeout(fun.id)
fun.id = setTimeout(function () {
fun.call(that, _args)
}, delay)
}
}
let inputb = document.getElementById('debounce')
let debounceAjax = debounce(ajax, 500)
inputb.addEventListener('keyup', function (e) {
debounceAjax(e.target.value)
})
//节流
function throttle(fun, delay) {
let last, deferTimer
return function (args) {
let that = this
let _args = arguments
let now = +new Date()
if (last && now < last + delay) {
clearTimeout(deferTimer)
deferTimer = setTimeout(function () {
last = now
fun.apply(that, _args)
}, delay)
}else {
last = now
fun.apply(that,_args)
}
}
}
let throttleAjax = throttle(ajax, 1000)
保护代理:
过滤请求
比如:权限的划分和管理
(5)中介者模式
定义:通过一个中介者对象,其他所有相关对象都通过该中介者对象来通信,而不是互相引用,当其中的一个对象发生改变时,只要通知中介者对象就可以。可以解除对象与对象之间的紧耦合关系。
应用场景: 例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。(一个事件的触发不会对其他对象造成影响)
(6)装饰者模式
定义:在不改变对象自身的基础上,在程序运行期间给对象动态的添加方法。
应用场景: 有方法维持不变,在原有方法上再挂载其他方法来满足现有需求;函数的解耦,将函数拆分成多个可复用的函数,再将拆分出来的函数挂载到某个函数上,实现相同的效果但增强了复用性。