1、代理模式

代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。

虚拟代理处理图片加载:

优点:

  • 在加载前使用loading占位;
  • 单一职责原则
  • 开放-封闭原则 ```jsx const loadingSrc = ‘xxxloading.gif’ const imgSrc = ‘.png’

const myImage = (() => { const imgNode = document.createElement(‘img’) document.body.appendChild(imgNode)

  1. return {
  2. setSrc: src => {
  3. imgNode.src = src
  4. }
  5. }

})()

const proxyImage = (function () { const img = new Image() img.onload = () => { myImage.setSrc(img.src) }

  1. return {
  2. setSrc: src => {
  3. myImage.setSrc(loadingSrc)
  4. img.src = src
  5. }
  6. }

})()

proxyImage.setSrc(imgSrc)

  1. <a name="JZsDJ"></a>
  2. # 2、观察者模式
  3. 当对象之间存在一对多的依赖关系时,其中一个对象的状态发生改变,所有依赖它的对象都会收到通知,这就是观察者模式。最常见的是订阅DOM事件;
  4. 实现发布订阅:[https://www.yuque.com/linhe-8mnf5/fxyxkm/fhe89i](https://www.yuque.com/linhe-8mnf5/fxyxkm/fhe89i)
  5. <a name="yQ07a"></a>
  6. # 3、单例模式
  7. 单例模式的定义是,保证一个类仅有一个实例,并提供一个访问它的全局访问点;
  8. 以下代码缺点:每次点击登录按钮,都会创建一个登录浮窗,频繁的创建 DOM 节点更加浪费性能。
  9. ```jsx
  10. <div id="loginBtn"></div>
  11. var createLoginLayer = () => {
  12. let div = document.createElement('div')
  13. div.innerHTML = '我是登录弹窗'
  14. div.style.display = 'none'
  15. document.body.appendChild(div)
  16. return div
  17. }
  18. document.getElementById('loginBtn').onclick = () => {
  19. const loginLayer = createLoginLayer()
  20. loginLayer.style.display = 'block'
  21. }

实际上我们只需要创建一次登录浮窗,通过单例模式重构代码。

  1. const createLoginLayer = () => {
  2. const div = document.createElement('div')
  3. div.innerHTML = '我是登录弹窗'
  4. div.style.display = 'none'
  5. console.log(123)
  6. document.body.appendChild(div)
  7. return div
  8. }
  9. const createSingle = (function () {
  10. var instance = {}
  11. return function (fn) {
  12. if (!instance[fn.name]) {
  13. instance[fn.name] = fn.apply(this, arguments)
  14. }
  15. return instance[fn.name]
  16. }
  17. })()
  18. const createSingleLoginLayer = createSingle(createLoginLayer)
  19. document.getElementById('loginBtn').onclick = () => {
  20. const loginLayer = createSingleLoginLayer
  21. loginLayer.style.display = 'block'
  22. }

4、策略模式

策略模式的定义是,定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。

传统做法:

  1. var calculateBonus = function(performanceLevel, salary) {
  2. if (performanceLevel === 'S') {
  3. return salary * 4;
  4. }
  5. if (performanceLevel === 'A') {
  6. return salary * 3;
  7. }
  8. if (performanceLevel === 'B') {
  9. return salary * 2;
  10. }
  11. };
  12. calculateBonus('B', 20000); // 输出:40000
  13. calculateBonus( 'S', 6000 ); // 输出:24000

缺点:

  • 使用 if-else 语句描述逻辑,代码庞大;
  • 缺乏弹性,如果需要修改绩效 S 的奖金系数,必须修改 calculateBonus 函数,违反了开放-封闭原则;
  • 无法再次复用,当其他地方需要用到这套逻辑,只能再复制一份。

使用策略模式:

  1. const strategies = {
  2. S: salary => {
  3. return salary * 4
  4. },
  5. A: salary => {
  6. return salary * 3
  7. },
  8. B: salary => {
  9. return salary * 2
  10. }
  11. }
  12. const calculateBonus = (level, salary) => {
  13. return strtegies[level](salary)
  14. }
  15. console.log(calculateBonus('s', 20000))
  16. console.log(calculateBonus('a', 10000))

优点:

  • 逻辑能复用
  • 消除大量的if-else语句
  • 将算法的使用和算法的实现分离,代码清晰,职责分明