单例模式

57 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天 单例模式

  • 什么是单例模式呢?
  • 我们都知道,构造函数可以创造一个对象
  • 我们 new 很多次构造函数就能得到很多的对象
  • 单例模式: 就是使用构造函数实例化的时候,不管实例化多少回,都是同一个对象
    • 也就是一个构造函数一生只能 new 出一个对象
  • 也就是说,当我们使用构造函数,每一次 new 出来的对象 属性/功能/方法 完全一样 的时候,我们把他设计成单例模式

核心代码

  • 单例模式的核心代码很简单

  • 其实就是判断一下,他曾经有没有 new 出来过对象

  • 如果有,就还继续使用之前的那个对象,如果没有,那么就给你 new 一个 // 准备一个构造函数 // 将来要 new 的 function Person() {}

    // 准备一个单例模式函数
    // 这个单例模式函数要把 Person 做成一个单例模式
    // 将来再想要 new Person 的时候只要执行这个 singleton 函数就可以了
    function singleton () {
      let instance
      
      if (!instance) { // 如果 instance 没有内容
        // 来到这里,证明 instance 没有内容
        // 给他赋值为 new Person
          instance = new Person()
      }
      
      // 返回的永远都是第一次 new Person 的实例
      // 也就是永远都是一个实例
      return instance
    }
    
    const p1 = singleton()
    const p2 = singleton()
    console.log(p1 === p2) // true
    

应用

  • 我们就用这个核心代码简单书写一个 demo // 这个构造函数的功能就是创建一个 div,添加到页面中 function CreateDiv() { this.div = document.createElement('div') document.body.appendChild(this.div) }

    CreateDiv.prototype.init = function (text) {
        this.div.innerHTML = text
    }
    
    // 准备把这个 CreateDiv 做成单例模式
    // 让 singleton 成为一个闭包函数
    const singleton = (function () {
    
        let instance
    
        return function (text) {
            if (!instance) {
                instance = new CreateDiv()
            }
            instance.init(text)
            return instance
        }
    })()
    
    singleton('hello') // 第一次的时候,页面中会出现一个新的 div ,内容是 hello
    singleton('world') // 第二次的时候,不会出现新的 div,而是原先的 div 内容变成了 world
    

组合模式

  • 组合模式,就是把几个构造函数的器动方式组合再一起

  • 然后用一个 ”遥控器“ 进行统一调用 class GetHome {

        init () {
            console.log('到家了')
        }
    }
    
    class OpenComputer {
    
        init () {
            console.log('打开电脑')
        }
    }
    
    class PlayGame {
    
        init () {
            console.log('玩游戏')
        }
    }
    
    • 上面几个构造函数的创造的实例化对象的 启动方式 都一致
    • 那么我们就可以把这几个函数以组合模式的情况书写
    • 然后统一启动
  • 准备一个 组合模式 的构造函数 class Compose { constructor () { this.compose = [] }

        // 添加任务的方法
        add (task) {
            this.compose.push(task)
        }
        
        // 一个执行任务的方法
        execute () {
            this.compose.forEach(item => {
                item.init()
            })
        }
    }
    
  • 我们就用我们的组合模式构造函数来吧前面的几个功能组合起来 const c = new Compose() // 把所有要完成的任务都放在队列里面 c.add(new GetHome()) c.add(new OpenComputer) c.add(new PlayGame)

    // 直接器动任务队列
    c.execute()
    // 就会按照顺序执行三个对象中的 init 函数
    

观察者模式

  • 观察者模式,通常也被叫做 发布-订阅模式 或者 消息模式
  • 英文名称叫做 Observer
  • 官方解释: 当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,解决了主体对象与观察者之间功能的耦合,即一个对象状态改变给其他对象通知的问题
  • 听起来很迷糊,但是其实没有很难

一个例子

  • 当你想去书店买书,但是恰巧今天你要买的书没有了
  • 我们又不能总在书店等着,就把我们的手机留给店员
  • 当你需要的书到了的时候,他会打电话通知你,你去买了就好了
  • 你买到数了以后,就告诉他,我买到了,那么以后再来了书就不会通知你了

addEventListener

  • 上面的例子可能还不是很明确
  • 但是 addEventListener 是一个我们都用过的东西
  • 这个东西其实就是一个标准的 观察者模式 btn.addEventListener('click', function () { console.log('btn 被点击了') })
    • 上面这个就是有一个 无形的观察者 再观察着 btn 的一举一动
    • 当这个 btn 被点击的时候,就会执行 对应的函数
    • 我们也可以多绑定几个函数
  • 说白了: 观察者模式就是我们自己实现一个 addEventListener 的功能
    • 只不过 addEventListaner 只有固定的一些事件,而且只能给 dom 元素绑定
    • 而我们自己写的可以随便绑定一个事件名称,自己选择触发时机而已