一、单例模式
应用:JQuery中的$,登录框,购物车,vuex,redux等
1.创建登录框
class LoginForm {
constructor() {
this.state = 'hide'
}
show() {
if (this.state === 'show') {
alert('已经显示')
return
}
this.state = 'show'
console.log('登录框已显示')
}
hide() {
if (this.state === 'hide') {
alert('已经隐藏')
return
}
this.state = 'hide'
console.log('登录框已隐藏')
}
}
LoginForm.getInstance = (function () {
let instance
return function () {
if (!instance) {
instance = new LoginForm();
}
return instance
}
})()
// 一个页面中调用登录框
let login1 = LoginForm.getInstance()
login1.show()
// login1.hide()
// 另一个页面中调用登录框
let login2 = LoginForm.getInstance()
login2.show()// 两者是否相等
console.log('login1 === login2', login1 === login2)
二、适配器模式
1、vue中的computed实际上也是适配器模式的一种应用,比如data里面的数据是hello,而模版需要的是一个倒叙的字符串,就可以在computed中返回return XXX.split('').reverse().join('')。
三、装饰器模式
es7已原生支持装饰器
日常开发中可以参考这个库core-decorators
装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。
四、代理模式
事件委托
经纪人代理明星
// 明星
let star = {
name: '张XX',
age: 25,
phone: '13910733521'
}
// 经纪人
let agent = new Proxy(star, {
get: function (target, key) {
if (key === 'phone') {
// 返回经纪人自己的手机号
return '18611112222'
}
if (key === 'price') {
// 明星不报价,经纪人报价
return 120000
}
return target[key]
},
set: function (target, key, val) {
if (key === 'customPrice') {
if (val < 100000) {
// 最低 10w
throw new Error('价格太低')
} else {
target[key] = val
return true
}
}
}
})
// 主办方
console.log(agent.name)
console.log(agent.age)
console.log(agent.phone)
console.log(agent.price)
// 想自己提供报价(砍价,或者高价争抢)
agent.customPrice = 150000
// agent.customPrice = 90000 // 报错:价格太低
console.log('customPrice', agent.customPrice)
五、外观模式
高层接口集成低层接口(洗衣机可以一键开洗也可以单独选择漂洗、干洗等,一键开洗也就集成了一些低层接口)
外观模式不符合单一职责原则和开放封闭原则,因此谨慎使用不可滥用。
六、观察者模式
简单实现
// 主题,接收状态变化,触发每个观察者
class Subject {
constructor() {
this.state = 0
this.observers = []
}
getState() {
return this.state
}
setState(state) {
this.state = state
this.notifyAllObservers()
}
attach(observer) {
this.observers.push(observer)
}
notifyAllObservers() {
this.observers.forEach(observer => {
observer.update()
})
}
}
// 观察者,等待被触发
class Observer {
constructor(name, subject) {
this.name = name
this.subject = subject
this.subject.attach(this)
}
update() {
console.log(`${this.name} update, state: ${this.subject.getState()}`)
}
}
// 测试代码
let s = new Subject()
let o1 = new Observer('o1', s)
let o2 = new Observer('o2', s)
let o3 = new Observer('o3', s)
s.setState(1)
s.setState(2)
s.setState(3)
应用场景:
(1)nodejs中:自定义事件,处理http请求(例如'data', 'end'事件),多进程通信
(2)vue和React组件生命周期触发
(3)vue watch
7.迭代器模式
实现一个简单的迭代器,支持遍历数组和类数组
class Iterator {
constructor(conatiner) {
this.list = conatiner.list
this.index = 0
}
next() {
if (this.hasNext()) {
return this.list[this.index++]
}
return null
}
hasNext() {
if (this.index >= this.list.length) {
return false
}
return true
}
}
class Container {
constructor(list) {
this.list = list
}
getIterator() {
return new Iterator(this)
}
}
// 测试代码
let container = new Container([1, 2, 3, 4, 5])
let iterator = container.getIterator()
while(iterator.hasNext()) {
console.log(iterator.next())
}
可迭代对象(以数组为例)原型上内置的迭代器
8、职责链模式
js中的promise.then方法,jq中的链式操作,nodejs的流
9、命令模式
js中的运用:富文本编辑器(浏览器封装了一个命令对象,例如document.execCommand('bold'),document.execCommand('undo'))