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