1、代理模式
代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。
虚拟代理处理图片加载:
优点:
- 在加载前使用loading占位;
- 单一职责原则
- 开放-封闭原则 ```jsx const loadingSrc = ‘xxxloading.gif’ const imgSrc = ‘.png’
const myImage = (() => { const imgNode = document.createElement(‘img’) document.body.appendChild(imgNode)
return {
setSrc: src => {
imgNode.src = src
}
}
})()
const proxyImage = (function () { const img = new Image() img.onload = () => { myImage.setSrc(img.src) }
return {
setSrc: src => {
myImage.setSrc(loadingSrc)
img.src = src
}
}
})()
proxyImage.setSrc(imgSrc)
<a name="JZsDJ"></a>
# 2、观察者模式
当对象之间存在一对多的依赖关系时,其中一个对象的状态发生改变,所有依赖它的对象都会收到通知,这就是观察者模式。最常见的是订阅DOM事件;
实现发布订阅:[https://www.yuque.com/linhe-8mnf5/fxyxkm/fhe89i](https://www.yuque.com/linhe-8mnf5/fxyxkm/fhe89i)
<a name="yQ07a"></a>
# 3、单例模式
单例模式的定义是,保证一个类仅有一个实例,并提供一个访问它的全局访问点;
以下代码缺点:每次点击登录按钮,都会创建一个登录浮窗,频繁的创建 DOM 节点更加浪费性能。
```jsx
<div id="loginBtn"></div>
var createLoginLayer = () => {
let div = document.createElement('div')
div.innerHTML = '我是登录弹窗'
div.style.display = 'none'
document.body.appendChild(div)
return div
}
document.getElementById('loginBtn').onclick = () => {
const loginLayer = createLoginLayer()
loginLayer.style.display = 'block'
}
实际上我们只需要创建一次登录浮窗,通过单例模式重构代码。
const createLoginLayer = () => {
const div = document.createElement('div')
div.innerHTML = '我是登录弹窗'
div.style.display = 'none'
console.log(123)
document.body.appendChild(div)
return div
}
const createSingle = (function () {
var instance = {}
return function (fn) {
if (!instance[fn.name]) {
instance[fn.name] = fn.apply(this, arguments)
}
return instance[fn.name]
}
})()
const createSingleLoginLayer = createSingle(createLoginLayer)
document.getElementById('loginBtn').onclick = () => {
const loginLayer = createSingleLoginLayer
loginLayer.style.display = 'block'
}
4、策略模式
策略模式的定义是,定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。
传统做法:
var calculateBonus = function(performanceLevel, salary) {
if (performanceLevel === 'S') {
return salary * 4;
}
if (performanceLevel === 'A') {
return salary * 3;
}
if (performanceLevel === 'B') {
return salary * 2;
}
};
calculateBonus('B', 20000); // 输出:40000
calculateBonus( 'S', 6000 ); // 输出:24000
缺点:
- 使用 if-else 语句描述逻辑,代码庞大;
- 缺乏弹性,如果需要修改绩效 S 的奖金系数,必须修改 calculateBonus 函数,违反了开放-封闭原则;
- 无法再次复用,当其他地方需要用到这套逻辑,只能再复制一份。
使用策略模式:
const strategies = {
S: salary => {
return salary * 4
},
A: salary => {
return salary * 3
},
B: salary => {
return salary * 2
}
}
const calculateBonus = (level, salary) => {
return strtegies[level](salary)
}
console.log(calculateBonus('s', 20000))
console.log(calculateBonus('a', 10000))
优点:
- 逻辑能复用
- 消除大量的if-else语句
- 将算法的使用和算法的实现分离,代码清晰,职责分明