- 公用某些资源
与数据库连接池,HTTP连接池很相似
使用HTTP连接池管理长连接,可以复用HTTP连接,省去创建TCP连接的3次握手和关闭TCP连接的4次挥手的步骤,降低请求响应的时间
使用场景:
- 如果一个程序中大量使用相同或相似对象,那么可以考虑引入享元模式
- 如果使用了相同或相似对象,并造成了较大的内存开销
- 对象的大多数状态可以被转变为外部状态
- 剥离出对象的外部状态后,可以用相对较少的共享对象取代大量对象
let examCardNum = 0 // 驾考车总数
class ExamCar {
constructor(carType) {
examCardNum++
this.cardId = examCardNum
this.carType = carType ? '手动挡' : '自动挡'
this.usingState = false // 是否正在占用
}
// 在本车上考试
examine(candidateId) {
return new Promise(resolve => {
this.usingState = true
console.log(`考生 ${candidateId} 在 ${this.carType}驾考车-${this.cardId}上考试`)
setTimeout(() => { // 0 - 2s 考完后
this.usingState = false
resolve()
}, Math.random() * 2000)
})
}
}
// 手动挡汽车对象池
ManualExamCarPool = {
_pool: [], // 驾考车对象池
_candidateQueue: [], // 考生队列
// 注册考生 ID 列表
registCandidates(candidateList) {
candidateList.forEach(candidateId => this.registCandidate(candidateId))
},
// 注册手动挡考生
registCandidate(candidateId) {
const examCar = this.getManualExamCar() // 找一个未被占用的手动挡驾考车
if (examCar) {
examCar.examine(candidateId) // 开始考试, 考完了让队列中的下一个考生开始考试
.then(() => {
const nextCandidateId = this._candidateQueue.length && this._candidateQueue.shift()
nextCandidateId && this.registCandidate(nextCandidateId)
})
} else { // 如果没有空车,将考生推入队列
this._candidateQueue.push(candidateId)
}
},
// 注册手动挡车
initManualExamCar(manualExamCarNum) {
for(let i = 0; i <= manualExamCarNum; i++) {
this._pool.push(new ExamCar(true))
}
},
// 获取状态为未被占用的手动挡车
getManualExamCar() {
return this._pool.find(car => !car.usingState)
}
}
ManualExamCarPool.initManualExamCar(3) // 一共三辆考车
ManualExamCarPool.registCandidates([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) // 10个考生来考试
网友评论