JS的设计模式

本文介绍了JavaScript中的三种设计模式:单例模式确保构造函数只创建一个实例,组合模式用于组合多个任务并统一调用,观察者模式则实现了事件监听和发布。通过示例代码详细解释了每种模式的工作原理及其应用。
摘要由CSDN通过智能技术生成

设计模式

单例模式 / 组合模式 / 观察者模式

单例模式

单例模式: 就是使用构造函数实例化的时候,不管实例化多少回,都是同一个对象
也就是一个构造函数一生只能 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



组合模式

组合模式,就是把几个构造函数的启动方式组合再一起,然后用一个 ”遥控器“ 进行统一调用

组合模式 的构造函数

  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


类似事件监听,观测绑定事件的对象的状态

 class Observer {			//观察者(这里抽象为一个对象 `{}`)
        constructor () {
            this.message = {}	//存放消息的盒子(把你绑定的所有事件放在里面)
        }
        
        on () {}				//on 方法,用于添加事件
        
        emit () {}				//emit 方法,用于发布事件(触发)
        	
        off () {}				//off 方法,把已经添加的方法取消
    }
ON

on 方法需要接受 两个参数

事件类型
事件处理函数

  class Observer {
      constructor () {
          this.message = {}
      }
      
      on (type, fn) {
          // 判断消息盒子里面有没有设置事件类型
          if (!this.message[type]) {
              // 证明消息盒子里面没有这个事件类型
              // 那么我们直接添加进去
              // 并且让他的值是一个数组,再数组里面放上事件处理函数
              this.message[type] = [fn]
          } else {
              // 证明消息盒子里面有这个事件类型
              // 那么我们直接向数组里面追加事件处理函数就行了
              this.message[type].push(fn)
          }
      }
      
      emit () {}
      
      off () {}
  }
EMIT

同样需要接受两个参数

要触发的事件类型
给事件处理函数传递的参数

  class Observer {
      constructor () {
          this.message = {}
      }
      
      on (type, fn) {
          // 判断消息盒子里面有没有设置事件类型
          if (!this.message[type]) {
              // 证明消息盒子里面没有这个事件类型
              // 那么我们直接添加进去
              // 并且让他的值是一个数组,再数组里面放上事件处理函数
              this.message[type] = [fn]
          } else {
              // 证明消息盒子里面有这个事件类型
              // 那么我们直接向数组里面追加事件处理函数就行了
              this.message[type].push(fn)
          }
      }
      
      emit (type, ...arg) {
          // 判断你之前有没有订阅过这个事件
          if (!this.message[type]) return
  
          // 如果有,那么我们就处理一下参数
          const event = {
              type: type,
              arg: arg || {}
          }
  
          // 循环执行为当前事件类型订阅的所有事件处理函数
          this.message[type].forEach(item => {
              item.call(this, event)
          })
      }
      
      off () {}
  }
OFF

同样需要接受两个参数

要移除的事件类型
要移除的事件处理函数

class Observer {
    constructor () {
        this.message = {}
    }
    
    on (type, fn) {
        // 判断消息盒子里面有没有设置事件类型
        if (!this.message[type]) {
            // 证明消息盒子里面没有这个事件类型
            // 那么我们直接添加进去
            // 并且让他的值是一个数组,再数组里面放上事件处理函数
            this.message[type] = [fn]
        } else {
            // 证明消息盒子里面有这个事件类型
            // 那么我们直接向数组里面追加事件处理函数就行了
            this.message[type].push(fn)
        }
    }
    
    emit (type, ...arg) {
        // 判断你之前有没有订阅过这个事件
        if (!this.message[type]) return

        // 如果有,那么我们就处理一下参数
        const event = {
            type: type,
            arg: arg || {}
        }

        // 循环执行为当前事件类型订阅的所有事件处理函数
        this.message[type].forEach(item => {
            item.call(this, event)
        })
    }
    
    off (type, fn) {
        // 判断你之前有没有订阅过这个事件
        if (!this.message[type]) return

        // 如果有我们再进行移除
        for (let i = 0; i < this.message[type].length; i++) {
            const item =  this.message[type][i]
            if (item === fn) {
                this.message[type].splice(i, 1)
                i--
            }
        }
    }
}
使用一下
const o = new Observer()

// 准备两个事件处理函数
function a(e) {
    console.log('hello')
}

function b(e) {
    console.log('world')
}

// 订阅事件
o.on('abc', a)
o.on('abc', b)

// 发布事件(触发)
o.emit('abc', '100', '200', '300') // 两个函数都回执行

// 移除事件
o.off('abc', 'b')

// 再次发布事件(触发)
o.emit('abc', '100', '200', '300') // 只执行一个 a 函数了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Raccom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值