千锋逆战班,Rayson.Jin学习打卡第二天!
今天给大家介绍一下JS设计模式。目前市场上设计模式有很多种,今天我们就学习常用的三种设计模式。
1.单例模式
2.组合模式
3.观察者模式
下面给大家逐个介绍一下
什么是设计模式
针对 特定问题, 给出的简洁而优化的处理方案
1.单例模式
01.作用
实例(构造函数的实例化对象)
让一个构造函数一辈子只有一个实例对象
当你需要一个构造函数一生只能 new 出一个对象的时候
就可以使用单例模式
02.核心代码
//准备一个构造函数
//将来要new的
function Person() {
//准备一个单列模式函数
//这个单列模式函数要把Person做成一个单例模式
//将来再想要new Person的时候只要执行这个singleton函数就可以了
this.name = 'Jack'
}
// 全局
var instance = null
function singleton() {
if (instance === null) {//如果insance没有内容
//来到这里,证明instance没有内容
//给它赋值为new Person
instance = new Person()
}
//返回的永远是第一次new Person的实例
//也就是永远都是一个实例
return instance
}
const p1 = singleton()
const p2 = singleton()
console.log(p1 === p2)//true
2.组合模式
01.作用
把我们若干这启动方式一样的构造函数放在一起
// 一个构造函数的启动方式
class Play {
constructor () {}
// 这个构造函数的启动方法
init () {
console.log('开始玩游戏')
this.a()
this.b()
}
a () {}
b () {}
}
02.核心代码
// 组合模式的代码
class Compose {
constructor () {
// 用来承载每一个实例的数组
this.composeArr = []
}
// 向数组里面添加内容
add (instance) {
this.composeArr.push(instance)
}
// 把数组里面的每一个内容调用了
init () {
console.log('总开关启动了')
this.composeArr.forEach(item => item.init())
}
}
// c 就是一个总开关
var c = new Compose()
// 每一次执行 add 方法就是向总开关上添加内容
c.add(new Play())
c.add(new Eat())
c.add(new Sleep())
// 只要我的总开关一启动
// 里面的每一个构造函数就同时都启动了
c.init()
console.log(c)
3.观察者模式
01.作用
也称为 发布-订阅模式 或者 消息模式
02.核心代码
需要一个观察者 这里抽象的定义为一个对象{}
需要一个属性,也称消息盒子(也就是要执行的所有事件)
需要一个on方法,向消息盒子中,添加事件
需要一个emit方法,用于发布事件
需要一个off方法,删除已经添加的方法
1.先定义观察者,消息盒子等方法
class Observer {//定义一个对象
constructor () {
// 准备的消息盒子
this.message = {}
}
// 订阅的方法
on ( ) { }//向消息盒子里面添加内容
emit ( ) { }//执行内容
off ( ) { }//删除内容
}
2.定义on方法、off方法和emit方法
class Observer {
constructor () {
// 准备的消息盒子
this.message = {}
}
// 订阅的方法
on (type, fn) {
// 向消息盒子里面添加成员
// type 事件类型, 你要订阅的类型
// fn 事件处理函数, 你要给这个类型订阅一个什么行为
// 假设我现在的 type === 'click'
// 消息盒子里面就应该是 { click: [handerA] }
// 如果消息盒子里面没有 click 这个成员, 那么我就创建一个这个成员是一个空数组
// 然后添加进去
// 如果消息盒子里面由这个 click 成员, 那么我直接 push 就可以了
if (!this.message[type]) {
// 表示 this.message 里面没有这个成员
this.message[type] = []
}
this.message[type].push(fn)
}
// 取消订阅的方法
off (type, fn) {
// 删除消息盒子里面的某一个成员
// type 是你要取消的事件类型
// fn 是你要取消的事件处理函数
// 先看看有没有这个事件类型, 如果没有, 不需要取消
// 如果由才需要取消
if (!this.message[type]) return
// 能执行到这里, 表示 this.message[type] 是一个数组
// 取消这个数组里面和 fn 一样的那个事件处理函数
// 使用一个 filter 方法
this.message[type] = this.message[type].filter(item => item !== fn)
}
// 发布的方法
emit (type) {
// 执行消息盒子里面的某一个对应的处理函数
// type 就是你要触发的事件类型
// 判断你有没有订阅过, 如果没有订阅过, 直接return
if (!this.message[type]) return
// 如果你订阅过, 那么就执行一下
this.message[type].forEach(item => item())
}
}
// 将来使用的时候
var o = new Observer()
// 订阅事件
o.on('click', handlerA)
o.on('click', handlerB)
// 取消订阅事件
// o.off('click', handlerA)
// 发布事件
// 把你订阅好的事件处理函数都给你触发了
console.log(o)
中国加油,武汉加油!千锋加油,自己加油!