设计模式:一种书写代码的方式,为解决特定问题给出的简介而优化的解决方案
1. 单例模式
/*单例模式单:单一例:实例一个构造函数一生只能有一个实例,不管你new多少次,都是这一个实例应用:自定义弹出层结构:div 》 xxxx, 默认隐藏,在一定条件下显示实现:每次都是一个div来回显示,只是内容不一样*/const Person = (function () {function Person(name, age) {this.name = namethis.age = age}let instance = nullreturn function singleTon(...args) {if (!instance) {instance = new Person(...args)}return instance}})()const p1 = new Person('Jack', 20)const p2 = new Person('Rose', 30)console.log(p1, p2)console.log(p1 === p2) // true
2. 观察者模式
/*观察者模式:+ 例子:监控=> 我们坐在教室里就是被观察者=> 监控后面的老师就是观察者=> 当被观察者触发了一些条件的时候,观察者就会触发技能+ 观察者模式:监控一个对象的状态,一旦状态发生变化,马上触发技能=> 需要两个构造函数来实现1. 创建被观察者=> 属性,自己的状态=> 队列,记录都有谁观察自己=> 方法1,能设置自己的状态,当我需要改变的时候,触发这个方法改变状态=> 方法2,添加观察者=> 方法3,删除观察者2. 创建观察者=> 需要一个身份证明=> 需要一个技能*/// 观察者构造函数class Observer {constructor(name, fn = () => {}) {this.name = namethis.fn = fn}}// 创建三个个观察者const njzr = new Observer('年级主任', (state) => {console.log('因为:' + state + '所以:告诉你的班主任')})const bzr = new Observer('班主任', (state) => {console.log('因为:' + state + '所以:把你爸找来')})const xz = new Observer('校长', (state) => {console.log('因为:' + state + '所以:骂你的班主任')})// console.log(bzr, xz)// 被观察者构造函数class Subject {constructor(state) {this.state = state // 记录自己的状态this.observers = [] // 保存观察着我的人}// 设置自己的状态setState(state) {this.state = state// 就需要把我的所有观察者的技能都触发// 遍历this.observers 依次触发技能this.observers.forEach(item => {// 把每一个观察者的技能触发// 告诉他我改变成了什么状态item.fn(this.state)})}// 添加观察者addObserver(obs) {this.observers = this.observers.filter(item => item !== obs)this.observers.push(obs)}// 删除观察者delObserver(obs) {this.observers = this.observers.filter(item => item !== obs)}}// 创建一个被观察者const xiaoming = new Subject('学习')xiaoming.addObserver(njzr)xiaoming.addObserver(bzr)xiaoming.addObserver(xz)console.log(xiaoming)const xiaohong = new Subject('学习')xiaohong.addObserver(bzr)xiaohong.addObserver(xz)console.log(xiaohong)
3. 发布订阅模式
/*
发布订阅模式
+ 有一个对象,有人在一直看着他
+ 当这个对象发生改变的时候,第三方通知这个看着的人,触发技能
+ 例子:买书
1. 普通程序员买书
=> 去书店,问,没有
=> 回家
=> 过一会儿再去,问,没有,回家
=> 过一会儿再去,问,没有,回家
2. 发布订阅的程序员
=> 去书店买书,问,没有,留下一个联系方式给店员
=> 一旦有了书,就会接到电话
=> 触发技能去买书
+ 只需要一个构造函数
=> 创建一个第三方店员的身份
=> 我们的任务就是模拟一个addEventListener()
分析构造函数
+ 属性:任务队列
{
click:[fn1, fn2]
abc:[fn1, fn2, fn3]
}
+ 方法1:能向消息队列里面添加内容
+ 方法2:删除队列里面的内容
+ 方法3:触发消息队列
*/
// 第三方观察者类
class Observer {
constructor() {
this.message = {}
}
// 1. 向消息队列里面添加内容
on(type, fn) {
// type: 我拜托你看着的行为
// fn: 在行为发生后,你要做的事情
// 把这些记录在消息队列中
// 1. 判断行为是否被注册过
if (!this.message[type]) {
this.message[type] = []
}
this.message[type].push(fn)
}
// 2. 删除消息队列里面的内容
off(type, fn) {
// fn不存在,只有一个参数的情况
if (!fn) {
// 直接把这个事情取消掉
delete this.message[type]
return
}
// fn存在
if (!this.message[type]) return // 没订阅过什么都不做
// 订阅过
this.message[type] = this.message[type].filter(item => item !== fn)
}
// 3. 触发消息队列
trigger(type) {
if (!this.message[type]) return // 判断是否被订阅过
this.message[type].forEach(item => {
item()
})
}
}
// 创建一个观察者实例
const person1 = new Observer()
console.log(person1)
// 当你想拜托这个person1帮你观察一些内容的时候
// 要告诉他一个行为,当行为出现的时候,告诉他该干什么(订阅一个行为)
person1.on('高程3', handlerA)
person1.on('高程3', handlerB)
person1.on('犀牛书', handlerC)
person1.on('犀牛书', handlerD)
// 1. 我的朋友送给我了犀牛书,我的这个事情不用你管了(取消订阅)
// person1.off('犀牛书')
// 2. 犀牛书来了,只去办C,不用去办D了
// person1.off('犀牛书', handlerD)
// person1.off('你不知道的js', handlerE)
// person一旦触发a行为,就要把后面所有的时间都进行处理
person1.trigger('高程3')
function handlerA() {
console.log('handlerA')
}
function handlerB() {
console.log('handlerB')
}
function handlerC() {
console.log('handlerC')
}
function handlerD() {
console.log('handlerD')
}
4. 策略模式
/*
策略模式
+ 一个问题可以匹配多个解决方案,不一定要用到哪一个
+ 而且有可能随时还会继续添加多个方案
+ 例子:购物车结算
=> 我们有好多种折扣计算方式
=> 满 100 减 10
=> 满 200 减 25
=> 8折
1. 把我们的多种方案,以闭包的形式保存起来
+ 按照传递进来的折扣和价格计算最终的价格返回
2. 留下添加折扣方式和删除折扣方式的接口
+ 函数也是一个对象
+ 可以把函数名当做一个对象,向里面添加一些成员
*/
// 接受两个参数,1. 价格 2. 折扣种类
// 如果现在多了一种折扣方式,我们就需要改源代码,加一个else if判断
// 活动结束后,还要删除这个方式
// function calcPrice(price, type) {
// if (type === '100_10') {
// price -= 10
// } else if (type === '200_25') {
// price -= 25
// } else if (type === '80%') {
// price *= 0.8
// } else {
// console.log('没有这种折扣方式')
// }
// return price
// }
// const res = calcPrice(320, '100_10')
// console.log(res)
// 1. 暂时以闭包的形式把折扣方案保存下来
const calcPrice = (function () {
const sale = {
'100_10': function (price) {
return price -= 10
},
'200_25': function (price) {
return price -= 25
},
'80%': function (price) {
return price *= 0.8
}
}
function calcPrice(price, type) {
if (!sale[type]) return '没有这个折扣方案'
return sale[type](price)
}
// 把函数当做一个对象,向里面添加一些成员
calcPrice.add = function (type, fn) {
// 判断折扣方式是否存在
if (sale[type]) return '该折扣方式已经存在'
sale[type] = fn
return '添加成功'
}
// 删除成员
calcPrice.del = function (type) {
delete sale[type]
}
return calcPrice
})()
const res = calcPrice.add('100_50', price => price -= 50)
// console.log(res)
let result = calcPrice(320, '100_50')
console.log(result)
