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 = createSingleLoginLayerloginLayer.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); // 输出:40000calculateBonus( '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语句
- 将算法的使用和算法的实现分离,代码清晰,职责分明
