设计模式只是一个概念性的东西,当我们编写应用程序的时候常常会用到很多面向对象的特性或者一些好的程序设计思路,可能会在下一次编程实践中用到,于是为了便于记忆取了一系列的名字,便有了设计模式这种东西。设计模式通常是在某些场合下一系列问题的解决方案,所以辨别模式的关键是这个模式出现的场景以及为我们解决了什么问题。
设计模式是为了增加代码的适应性,同是为代码维护带来便捷。
学习设计模式能更好的理解面向对象编程思想。
1. 单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
应用场景:假设我们的页面有个登录按钮,点击会出现一个登录浮窗,这个浮窗是唯一的无论你点了多少次登录按钮。这时候我们就需要单例模式来创建
在点击按钮之前先判断浮窗是否已存在,如果有就只显示,没有就新创建浮窗。
// 把创建单例的函数抽象出来
const createSingle = function (fn) {
// 声明一个变量缓存结果
let result
return function (...args) {
// 如果这个单例已存在就直接返回结果,否者调用它并且把结果缓存
return result || (result = fn.apply(this, args))
}
}
// 创建单例登录弹窗的函数(注意传入的函数需要有返回值)
const createLoginLayer = createSingle(function () {
const div = document.createElement('div')
div.innerHTML = '我是登录按钮'
div.style.display = 'none'
document.body.appendChild(div)
return div
})
// 给登录按钮绑定点击事件
document.getElementById('loginBtn').onclick = function () {
let loginLayer = createLoginLayer()
loginLayer.style.display = 'block'
}
2.策略模式
定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
应用场景:假设需要通过员工绩效去计算员工的工资,绩效为A的是4倍工资,B是3倍工资,C是2倍工资,D是1倍工资,我们可以将绩效算法封装成一个对象,通过一个方法去调用它。
// 封装策略规则
const strategies = {
A (salary) {
return salary * 4
},
B (salary) {
return salary * 3
},
C (salary) {
return salary * 2
},
D (salary) {
return salary * 1
}
}
// 使用功能接口
const calcSalary = function (performance, salary) {
return strategies[performance](salary)
}
// 可以看出calcSalary并没有计算奖金的功能,而是把功能委托给了封装好的策略对象strategies
3.代理模式
为一个对象提供一个代用品或占位符,以便控制对它的访问。
1.当我们需要给对象添加新功能而又不想直接修改对象,这时候就需要靠代理来实现。
2.代理与本体可以各自变化而不影响对方,减少代码的耦合性。
3.代理与本体接口应保持一致性,能让用户放心的请求代理去得到他想要的结果,同时代理与本体之间可以替换使用。
应用场景,图片的预加载。
// 添加一张图片的类
const myImage = (function () {
const img = document.createElement('img')
document.body.appendChild(img)
return {
setSrc: function (src) {
img.src = src
}
}
})()
// 代理对象
const proxyImage = (function () {
const img = new Image
img.onload = function () {
myImage.setSrc(this.src)
}
return {
setSrc: function (src) {
myImage.setSrc('file:// /C:/Users/svenzeng/Desktop/loading.gif')
img.src = src
}
}
})()
// 我们通过proxyImage间接访问了myImage,这样我们可以在图片加载前做一些预加载的操作。
proxyImage.setSrc('http:// imgcache.qq.com/music/photo/k/000GGDys0yA0Nk.jpg')
// 我们也可以不使用代理,这并不影响添加图片这一功能的实现。
myImage.setSrc('http:// imgcache.qq.com/music/photo/k/000GGDys0yA0Nk.jpg')
4.迭代器模式
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象
的内部表示。
应用场景:JS有内置迭代器forEach,我们也可以手动去实现它。
Array.prototype.forEach = function (callback) {
for (let i = 0; i < this.length; i ++) {
callback.call(this, this[i], i)
}
}
网友评论