前言
观察者模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。
观察者模式
使用场景:常见的观察者模式的使用就是发布订阅,比如拍卖商品,还有过节抢火车票、飞机票、电影票之类的。这种模式比较常见,当目标对象有变化了,关注这个目标的其它人也会迅速做出相应的反应。
理解:这是一种类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,这种方式有点花,但非常实用,当目标发生变化,其它关注目标的其它人就会做出相关反应。这个代码例子似乎结合了电影院买票和拍卖竞拍,原理一致,比如你用手机APP买票,如果别人选了你想要的票,那么你就不能再选这个票了,然后你就只能选其它的票。观察者需要关注这个目标,而这个目标也需要把观察者添加到候选名单中,这样目标和观察者就能相互调用,它们之间的调用是基于行为上的交互,也都封装到内部的方法中,所以能很好的将类、对象的行为和使用解耦了。
namespace action_mode_01 {
// 票
class Ticket {
id: string
position: string
state: boolean
user: string = ''
price: number
constructor(id: string, position: string) {
this.id = id;
this.position = position;
this.price = ~~ (Math.random() * 1000)
this.state = false;
}
// 买票,返回是否购买成功的状态
buy() {
if (this.isBuy()) {
return false
}
this.state = true
return this.state
}
isBuy() {
return this.state
}
}
// 目标:电影院卖票
class Cinema {
ticketBuyerList: Array<TicketBuyer> = []
ticketList: Array<Ticket> = []
addTicketBuyer(ticketBuyer: TicketBuyer) {
this.ticketBuyerList.push(ticketBuyer)
}
constructor() {
// 初始化十张电影票
for (let i = 0; i < 10; i++) {
const id = String(~~ (1000000000 * Math.random()));
const position = String(i)
const ticket = new Ticket(id, position)
this.ticketList.push(ticket)
}
}
startSell () {
this.ticketBuyerList.forEach(item => {
item.buyTicket(~~ (Math.random() * 1000))
});
const tempList = this.ticketList.filter(item => item.isBuy())
if (tempList.length === this.ticketList.length) {
console.log('======================================');
console.log('============⭐⭐⭐⭐⭐⭐===========');
console.log('本场电影票已卖完,买票成功的人员名单如下:');
console.log('============⭐⭐⭐⭐⭐⭐===========');
console.log('======================================');
tempList.forEach(item => {
console.log(`票号:${item.id} 位置:${item.position} 买主是:${item.user}`)
})
return true
}
return false
}
sellTicket (ticketBuyer: TicketBuyer, money: number) {
ticketBuyer.isBuy = false
this.ticketList.forEach(item => {
// 价格低或者本轮已经买过了
if (money >= item.price && !ticketBuyer.isBuy) {
const result = item.buy()
// 购买成功
if (result) {
ticketBuyer.isBuy = true
ticketBuyer.mytickets.push(item)
item.user = ticketBuyer.name
console.log(item.user + ' 买票成功! 票号是:' + item.id + ' 位置是:' + item.position)
} else {
// 购买失败
console.log('票号:' + item.id + ' 位置:' + item.position + ',买主:' + item.user + ' 买票失败! ')
}
}
})
}
}
// 观察者:买票黄牛
class TicketBuyer {
name: string
cinema: Cinema
isBuy: boolean = false
mytickets: Array<Ticket> = []
constructor (cinema: Cinema, name: string) {
this.cinema = cinema
this.name = name
// this.cinema.addTicketBuyer(this) // 也可以在这里添加让目标把观察者添加进去
}
// 买票
buyTicket ( money: number) {
this.cinema.sellTicket(this, money)
}
}
// 使用
const cinema = new Cinema()
for (let i = 0; i < 99; i++) {
const t = new TicketBuyer(cinema, '黄牛'+i+'号')
cinema.addTicketBuyer(t)
}
let result = cinema.startSell()
while(!result) {
result = cinema.startSell()
}
}