我学会了,观察者模式

简介: 观察者模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。

前言

观察者模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。

观察者模式

使用场景:常见的观察者模式的使用就是发布订阅,比如拍卖商品,还有过节抢火车票、飞机票、电影票之类的。这种模式比较常见,当目标对象有变化了,关注这个目标的其它人也会迅速做出相应的反应。

理解:这是一种类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,这种方式有点花,但非常实用,当目标发生变化,其它关注目标的其它人就会做出相关反应。这个代码例子似乎结合了电影院买票和拍卖竞拍,原理一致,比如你用手机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()
    }
}
目录
相关文章
|
Java 测试技术 Go
利用 GitHub Action 自动发布 Docker
最近公司内部项目的发布流程接入了 GitHub Actions,整个体验过程还是比较美好的;本文主要目的是对于没有还接触过 GitHub Actions的新手,能够利用它快速构建自动测试及打包推送 Docker 镜像等自动化流程。
|
6月前
域名优惠包使用帮助文档
本文详细介绍域名优惠包的使用步骤,让您在优惠包使用过程中操作更便捷。
319 2
域名优惠包使用帮助文档
|
Android开发
Flutter控件的显示与隐藏
Flutter控件的显示与隐藏
456 3
|
7月前
|
计算机视觉
YOLOv11改进策略【Neck】| PRCV 2023,SBA(Selective Boundary Aggregation):特征融合模块,描绘物体轮廓重新校准物体位置,解决边界模糊问题
YOLOv11改进策略【Neck】| PRCV 2023,SBA(Selective Boundary Aggregation):特征融合模块,描绘物体轮廓重新校准物体位置,解决边界模糊问题
303 11
|
10月前
光纤电缆:优点与缺点深度解析
【10月更文挑战第21天】
362 1
|
11月前
|
存储 编译器 数据安全/隐私保护
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解2
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
141 3
|
编解码 Android开发
【Android Studio】使用UI工具绘制,ConstraintLayout 限制性布局,快速上手
本文介绍了Android Studio中使用ConstraintLayout布局的方法,通过创建布局文件、设置控件约束等步骤,快速上手UI设计,并提供了一个TV Launcher界面布局的绘制示例。
292 1
|
存储 监控 测试技术
如果做好一位需求分析师
如果做好一位需求分析师
275 0
|
存储 缓存 JavaScript
JavaScript本地存储的方式有哪些
本文介绍了四种Web存储技术:localStorage用于长期存储用户数据,关闭浏览器后仍保留;sessionStorage仅在会话期间存储数据,浏览器关闭后消失;Cookie存储少量字符串数据,通常用于用户身份识别;IndexedDB则用于大量结构化数据的存储,适合复杂应用的需求。每种技术都有其特定的使用场景和优缺点。
233 0
|
XML 缓存 Java
Gradle 构建自动化工具入门
Gradle 构建自动化工具入门