TS设计模式之观察者模式

本文介绍了观察者模式的基本概念,通过4S店和购车顾客的实例阐述了模式的工作原理。接着展示了如何通过接口和类来实现代码,包括发布者和订阅者角色。文章还分析了模式的优点和缺点,强调了其遵循的开闭原则,以及作者计划持续分享设计模式的内容以求完善。
摘要由CSDN通过智能技术生成
1.概述

观察者模式又称为发布订阅者模式。该模式在日常生活中十分常见,小白敲了十年的代码终于攒够了钱准备去买一辆跑车,但是当小白到4s店被告知现在没有这辆车了,销售喊小白留一下自己的电话当有新车的时候通知小白。在这个例子中,小白和其它想要购买这辆跑车的顾客都为订阅者,4s店则是发布者,当有新车时通过电话或短信的形式发布消息给顾客。

2.代码实现思路

在同一个4S店中会有多个顾客等待同一辆车,若是不规定发送消息的方式可能会非常乱,有的顾客选择邮箱接收消息,有的顾客选择手机短信,有的顾客选择微信通知.....,我们需要定义一个订阅者接口ListenersInterface规范这些方式,统一选择打电话通知,最好给4S店也定义一个接口EventMangerInterface对4S店进行规范,EventMangerInterface接口中定义一个存放订阅者的数下,新增订阅者,删除订阅者,以及通知订阅者的方法,在ListenersInterface中定义一个接收通知的方法,当发布者调用通知订阅者的方法后,订阅者会通过该方法来进行接收。

3.代码实现

接下来将通过一个监听文件打开关闭的代码来实现该模式

1.发布者代码
// 订阅类型
type listenerType = 'close' | 'open'

// 发布者接口
interface EventManagerInterface {
    // 订阅者
    listeners: Map<listenerType, ObserverInterface[]>
    // 加入订阅
    subscribe(type: listenerType, listener: ObserverInterface): void
    // 取消订阅
    unSubscribe(type: listenerType, listener: ObserverInterface): void
    // 发布消息
    notify(type: listenerType): void
}

export class FilePublish implements EventManagerInterface{
    listeners: Map<listenerType, ObserverInterface[]> = new Map()

    notify(type: listenerType): void {
        let currentListeners = this.listeners.get(type)
        if(!currentListeners) {
            throw Error('no found listener in this instance')
        }
        currentListeners.forEach((item: ObserverInterface)=>{
            item.update()
        })
    }

    subscribe(type: listenerType, listener: ObserverInterface): void {
        let currentListeners = this.listeners.get(type)
        if(!currentListeners) {
            currentListeners = []
        }
        if(currentListeners.findIndex(item=>listener === item) === -1) {
            currentListeners.push(listener)
        }
        this.listeners.set(type, currentListeners)
    }

    unSubscribe(type: listenerType, listener: ObserverInterface): void {
        let currentListeners = this.listeners.get(type)
        if(!currentListeners) {
            throw Error('no found Listener in this instance')
        }
        let index = currentListeners.findIndex(item=>listener === item)
        if(!index) {
            throw Error('no found Listener in this instance')
        }
        currentListeners = currentListeners.splice(index, 1)
        this.listeners.set(type, currentListeners)
    }

    // 打开文件
    async openFile() {
        this.notify('open')
    }

    // 关闭文件
    async closeFile() {
        this.notify('close')
    }

}
2.订阅者代码
// 订阅者接口
interface ObserverInterface {
    update(): void
}

// 监听文件打开类
export class FileOpenListener implements ObserverInterface {
    update() {
        alert('文件打开了')
    }
}

// 监听文件关闭类
export class FileCloseListener implements ObserverInterface {
    update() {
        alert('文件关闭了')
    }
}
3. 客户端代码
<template>
  <button @click="onOpen">打开文件</button>
  <button @click="onClose">关闭文件</button>
</template>

<script setup lang="ts">
import {FileCloseListener, FileOpenListener, FilePublish} from "@/util/ObserverPattern";
const filePublish = new FilePublish()
const fileCloseListener = new FileCloseListener()
const fileOpenListener = new FileOpenListener()
filePublish.subscribe('open', fileOpenListener)
filePublish.subscribe('close', fileCloseListener)

const onOpen = ()=>{
  filePublish.openFile()
}

const onClose = ()=>{
  filePublish.closeFile()
}


</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
4.模式的优缺点
1. 优点

符合开闭原则,订阅者或者发布者需要添加功能时,只需要实现接口进行扩展即可,不需要修改源代码。

2.缺点

该模式不能对订阅者进行排序,若是车少想买车的顾客多时很容易发生冲突。

5.结语

小白每周尽量会多生产几篇设计模式内容,若对设计模式的理解有不正确之处请评论指正,小白会虚心接受,教学相长也。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值