观察者模式定义与案例详解:一文看懂设计模式中观察者模式原理与应用
如果你做后端开发做了两三年,肯定听过设计模式这个词,不少人刚接触的时候会觉得这些概念太抽象,不知道学了能干嘛。今天我们就聊设计模式里最常用的观察者模式,用普通人都能听懂的话讲清楚,再结合实际项目案例说它怎么用。
先举个生活里的例子你就懂了。你平时刷短视频,刷到喜欢的博主是不是会点个关注?之后这个博主发新内容,平台就会给你推送提醒。要是你觉得不好看了,随时也能取消关注,再也收不到消息。
观察者模式做的就是一模一样的事情。这里,你就是"观察者",发内容的博主就是"被观察者",你关注博主就是绑定关系,博主发内容主动通知所有粉丝,就是观察者模式的核心逻辑。
放到程序设计里说,观察者模式定义其实就是:定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。
talk is cheap,我们拆解开来看它的结构。观察者模式里一共就两种核心角色,第一种是被观察者,也有人叫它主题(Subject),它的作用就是管理观察者,负责添加、删除观察者,还要在自身状态变化的时候,通知所有观察者更新。第二种就是观察者(Observer),只要给观察者定一个统一的更新接口,不同的观察者实现自己的更新逻辑就行,被观察者通知的时候,大家各自干各自的事。
这么说还是有点干?我们接着刚才的例子套进去。被观察者就是博主,它要管自己的粉丝列表,粉丝关注就加进去,取消就删掉,发新视频的时候,挨个通知所有粉丝说我更内容了。观察者就是每个粉丝,每个粉丝收到通知之后,做什么完全可以自己定,有的粉丝看到通知就点进去看,有的粉丝可能只存着之后有空再看,完全不影响其他人,也不影响博主。
很多新手刚学的时候会问,我不直接调用方法不行吗?为啥要搞这么个模式出来。其实好处说出来你就懂了。
最大的好处就是解耦。什么叫解耦?就是把会变的代码和不变的代码分开,博主不用管粉丝收到通知之后具体要做什么,也不用记都有哪些类型的粉丝,只要按规则发通知就行。以后加新粉丝,不用改博主这边的代码,符合设计模式里的"开闭原则"——对扩展开放,对修改关闭。
比如说我们做电商网站,用户下单成功之后,要做一堆事:给用户发推送短信、扣优惠券、给财务发对账消息、统计订单数据进数据仓库。如果不使用观察者模式,你是不是会把这些逻辑全写在下单成功的方法里?下单方法本来只需要处理生成订单扣库存,现在塞了一堆其他逻辑,代码越来越长,以后要加个新功能,比如下单之后推送给积分商城加积分,你又得改下单的核心代码,改多了很容易出bug,把原来的功能改坏。
用观察者模式就不一样了。下单这个动作本身就是被观察者,下单成功状态一变,就通知所有观察者。发短信是一个观察者,扣优惠券是一个,发对账消息又是另一个,每个功能都写在自己的类里,互不影响。以后要加积分功能,直接新增一个观察者类,加到被观察者的列表里就行,完全不用改下单的核心代码,风险低很多,也方便后期维护。
我们再写个简单的伪代码,大家更明白点。先定一个观察者的接口,就叫Observer,里面就一个方法update,参数传博主发的新内容就行。
然后是被观察者,也就是博主类Blogger,里面有一个List存所有观察者,也就是粉丝。然后提供三个方法:addObserver就是加粉丝,removeObserver就是删粉丝,notifyObserver就是遍历所有观察者调用它们的update方法。
publishNewContent就是发新文章,内容写好之后调用notifyObserver发通知,整个逻辑就通了。
具体的粉丝就是实现Observer接口,比如普通粉丝CommonFan,update方法里就是打印一句"我收到推送了,马上来看新内容"。还有一种可能是营销号粉丝,专门等博主发内容蹭热度,它的update方法里就是"收到推送,赶紧准备蹭热度文案",不同逻辑分开写,清晰得很。
你用的时候,只要新建一个博主,加几个不同的粉丝,博主一发内容,所有粉丝自动收到通知干活,完全不用博主管每个粉丝做什么。
实际开发里观察者模式用得太多了,除了刚才说的电商下单,还有很多常见场景。
比如说你做消息队列,生产者发消息,消费者订阅队列,生产者就是被观察者,消费者就是观察者,生产者发完消息,所有订阅的消费者都能收到,这本身就是观察者模式的实现。还有前端开发里的DOM事件监听,你给一个按钮addEventListener绑定点击事件,其实这个按钮就是被观察者,你写的点击回调就是观察者,按钮点击状态变了,就通知你的回调执行,完全是观察者模式的逻辑。
还有你用Spring框架,Spring里面的事件驱动机制,ApplicationEvent和ApplicationListener,本质上就是观察者模式。你要自定义一个事件,继承ApplicationEvent,然后写一个*实现ApplicationListener,发布事件的时候ApplicationContext调用publishEvent,所有对应的*就会自动执行,和我们刚才说的博主粉丝逻辑一模一样。
当然,观察者模式也不是全是优点,也有要注意的地方。如果被观察者的观察者特别多,那通知所有观察者就要花不少时间,影响性能。如果观察者之间有依赖关系,比如一个观察者更新会触发另一个观察者更新,搞不好会出现循环调用,把系统搞崩,这都是用的时候要注意规避的问题。
总的来说,观察者模式就是一个帮你把复杂逻辑拆解开的工具,遇到一个动作触发多个后续处理的场景,用它准没错,能让你的代码好维护太多,新手学会之后,可以先在自己的项目里试着用一次,用一次就明白它到底香在哪了。
观察者模式,设计模式,观察者模式原理,观察者模式定义,观察者模式应用,观察者模式案例,设计模式观察者,被观察者,观察者,开闭原则
[Q]:什么是观察者模式?
[A]:观察者模式是一种设计模式,核心是定义对象间一对多的依赖关系,当被观察者(主题)状态改变时,会自动通知所有依赖它的观察者对象完成更新,可以用生活里博主和粉丝的关系类比:粉丝关注博主后,博主发新内容会主动推送通知给所有粉丝。
[Q]:观察者模式有哪几个核心角色?
[A]:观察者模式只有两个核心角色,分别是被观察者(主题)和观察者,被观察者负责管理观察者列表、状态改变时通知观察者;观察者定义统一更新接口,不同观察者实现自身的更新逻辑。
[Q]:观察者模式最大的优点是什么?
[A]:观察者模式最大的优点就是解耦,它将核心逻辑和后续扩展逻辑拆分开,符合开闭原则,新增功能时不需要修改原有核心代码,降低了代码修改带来的风险,也更方便后期维护。
[Q]:观察者模式适合用在什么开发场景?
[A]:适合一个状态变化需要触发多个后续处理的场景,常见的有电商下单成功后的多业务处理、消息队列的生产者消费者模型、前端DOM事件监听、Spring的事件驱动机制等。
[Q]:什么是开闭原则,观察者模式怎么符合开闭原则?
[A]:开闭原则就是对扩展开放,对修改关闭,观察者模式中新增业务处理逻辑只需要新增对应的观察者类,不需要修改被观察者的核心代码,因此天然符合开闭原则。
[Q]:观察者模式有什么缺点吗?
[A]:如果被观察者绑定的观察者数量很多,遍历通知所有观察者会消耗更多时间影响性能;如果观察者之间存在依赖关系,还可能出现循环调用,导致系统运行异常,这些都是使用时需要注意规避的问题。
[Q]:Spring的事件机制和观察者模式有关系吗?
[A]:Spring的事件驱动机制本质就是观察者模式的实现,自定义事件继承ApplicationEvent,*实现ApplicationListener,发布事件后所有对应的*就会自动执行,和观察者模式的核心逻辑完全一致。
[Q]:前端的DOM事件监听和观察者模式有关吗?
[A]:有关系,DOM元素就是被观察者,我们绑定的点击等事件回调就是观察者,当DOM元素状态发生改变(比如被点击),就会自动通知所有绑定的回调函数执行,本身就是观察者模式的应用。
先举个生活里的例子你就懂了。你平时刷短视频,刷到喜欢的博主是不是会点个关注?之后这个博主发新内容,平台就会给你推送提醒。要是你觉得不好看了,随时也能取消关注,再也收不到消息。
观察者模式做的就是一模一样的事情。这里,你就是"观察者",发内容的博主就是"被观察者",你关注博主就是绑定关系,博主发内容主动通知所有粉丝,就是观察者模式的核心逻辑。
放到程序设计里说,观察者模式定义其实就是:定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。
talk is cheap,我们拆解开来看它的结构。观察者模式里一共就两种核心角色,第一种是被观察者,也有人叫它主题(Subject),它的作用就是管理观察者,负责添加、删除观察者,还要在自身状态变化的时候,通知所有观察者更新。第二种就是观察者(Observer),只要给观察者定一个统一的更新接口,不同的观察者实现自己的更新逻辑就行,被观察者通知的时候,大家各自干各自的事。
这么说还是有点干?我们接着刚才的例子套进去。被观察者就是博主,它要管自己的粉丝列表,粉丝关注就加进去,取消就删掉,发新视频的时候,挨个通知所有粉丝说我更内容了。观察者就是每个粉丝,每个粉丝收到通知之后,做什么完全可以自己定,有的粉丝看到通知就点进去看,有的粉丝可能只存着之后有空再看,完全不影响其他人,也不影响博主。
很多新手刚学的时候会问,我不直接调用方法不行吗?为啥要搞这么个模式出来。其实好处说出来你就懂了。
最大的好处就是解耦。什么叫解耦?就是把会变的代码和不变的代码分开,博主不用管粉丝收到通知之后具体要做什么,也不用记都有哪些类型的粉丝,只要按规则发通知就行。以后加新粉丝,不用改博主这边的代码,符合设计模式里的"开闭原则"——对扩展开放,对修改关闭。
比如说我们做电商网站,用户下单成功之后,要做一堆事:给用户发推送短信、扣优惠券、给财务发对账消息、统计订单数据进数据仓库。如果不使用观察者模式,你是不是会把这些逻辑全写在下单成功的方法里?下单方法本来只需要处理生成订单扣库存,现在塞了一堆其他逻辑,代码越来越长,以后要加个新功能,比如下单之后推送给积分商城加积分,你又得改下单的核心代码,改多了很容易出bug,把原来的功能改坏。
用观察者模式就不一样了。下单这个动作本身就是被观察者,下单成功状态一变,就通知所有观察者。发短信是一个观察者,扣优惠券是一个,发对账消息又是另一个,每个功能都写在自己的类里,互不影响。以后要加积分功能,直接新增一个观察者类,加到被观察者的列表里就行,完全不用改下单的核心代码,风险低很多,也方便后期维护。
我们再写个简单的伪代码,大家更明白点。先定一个观察者的接口,就叫Observer,里面就一个方法update,参数传博主发的新内容就行。
然后是被观察者,也就是博主类Blogger,里面有一个List存所有观察者,也就是粉丝。然后提供三个方法:addObserver就是加粉丝,removeObserver就是删粉丝,notifyObserver就是遍历所有观察者调用它们的update方法。
publishNewContent就是发新文章,内容写好之后调用notifyObserver发通知,整个逻辑就通了。
具体的粉丝就是实现Observer接口,比如普通粉丝CommonFan,update方法里就是打印一句"我收到推送了,马上来看新内容"。还有一种可能是营销号粉丝,专门等博主发内容蹭热度,它的update方法里就是"收到推送,赶紧准备蹭热度文案",不同逻辑分开写,清晰得很。
你用的时候,只要新建一个博主,加几个不同的粉丝,博主一发内容,所有粉丝自动收到通知干活,完全不用博主管每个粉丝做什么。
实际开发里观察者模式用得太多了,除了刚才说的电商下单,还有很多常见场景。
比如说你做消息队列,生产者发消息,消费者订阅队列,生产者就是被观察者,消费者就是观察者,生产者发完消息,所有订阅的消费者都能收到,这本身就是观察者模式的实现。还有前端开发里的DOM事件监听,你给一个按钮addEventListener绑定点击事件,其实这个按钮就是被观察者,你写的点击回调就是观察者,按钮点击状态变了,就通知你的回调执行,完全是观察者模式的逻辑。
还有你用Spring框架,Spring里面的事件驱动机制,ApplicationEvent和ApplicationListener,本质上就是观察者模式。你要自定义一个事件,继承ApplicationEvent,然后写一个*实现ApplicationListener,发布事件的时候ApplicationContext调用publishEvent,所有对应的*就会自动执行,和我们刚才说的博主粉丝逻辑一模一样。
当然,观察者模式也不是全是优点,也有要注意的地方。如果被观察者的观察者特别多,那通知所有观察者就要花不少时间,影响性能。如果观察者之间有依赖关系,比如一个观察者更新会触发另一个观察者更新,搞不好会出现循环调用,把系统搞崩,这都是用的时候要注意规避的问题。
总的来说,观察者模式就是一个帮你把复杂逻辑拆解开的工具,遇到一个动作触发多个后续处理的场景,用它准没错,能让你的代码好维护太多,新手学会之后,可以先在自己的项目里试着用一次,用一次就明白它到底香在哪了。
观察者模式,设计模式,观察者模式原理,观察者模式定义,观察者模式应用,观察者模式案例,设计模式观察者,被观察者,观察者,开闭原则
[Q]:什么是观察者模式?
[A]:观察者模式是一种设计模式,核心是定义对象间一对多的依赖关系,当被观察者(主题)状态改变时,会自动通知所有依赖它的观察者对象完成更新,可以用生活里博主和粉丝的关系类比:粉丝关注博主后,博主发新内容会主动推送通知给所有粉丝。
[Q]:观察者模式有哪几个核心角色?
[A]:观察者模式只有两个核心角色,分别是被观察者(主题)和观察者,被观察者负责管理观察者列表、状态改变时通知观察者;观察者定义统一更新接口,不同观察者实现自身的更新逻辑。
[Q]:观察者模式最大的优点是什么?
[A]:观察者模式最大的优点就是解耦,它将核心逻辑和后续扩展逻辑拆分开,符合开闭原则,新增功能时不需要修改原有核心代码,降低了代码修改带来的风险,也更方便后期维护。
[Q]:观察者模式适合用在什么开发场景?
[A]:适合一个状态变化需要触发多个后续处理的场景,常见的有电商下单成功后的多业务处理、消息队列的生产者消费者模型、前端DOM事件监听、Spring的事件驱动机制等。
[Q]:什么是开闭原则,观察者模式怎么符合开闭原则?
[A]:开闭原则就是对扩展开放,对修改关闭,观察者模式中新增业务处理逻辑只需要新增对应的观察者类,不需要修改被观察者的核心代码,因此天然符合开闭原则。
[Q]:观察者模式有什么缺点吗?
[A]:如果被观察者绑定的观察者数量很多,遍历通知所有观察者会消耗更多时间影响性能;如果观察者之间存在依赖关系,还可能出现循环调用,导致系统运行异常,这些都是使用时需要注意规避的问题。
[Q]:Spring的事件机制和观察者模式有关系吗?
[A]:Spring的事件驱动机制本质就是观察者模式的实现,自定义事件继承ApplicationEvent,*实现ApplicationListener,发布事件后所有对应的*就会自动执行,和观察者模式的核心逻辑完全一致。
[Q]:前端的DOM事件监听和观察者模式有关吗?
[A]:有关系,DOM元素就是被观察者,我们绑定的点击等事件回调就是观察者,当DOM元素状态发生改变(比如被点击),就会自动通知所有绑定的回调函数执行,本身就是观察者模式的应用。
更多观察者模式定义与案例详解:一文看懂设计模式中观察者模式原理与应用相关问题
问题:《恋与制作人》识别组织时间到(?)
回答:云星双子出地狱不知道jj开龙右 详情 >
问题:《DOTA2》比赛模式设计:大黑屋模式(Foe Draft)
回答:建议五天玩起来比较合适 详情 >
问题:《英雄联盟》当你在无CD模式中选出蛮王,无限大招硬拆塔,对面心态快要崩了!
回答:我喜欢出天堂蝴蝶 25级游泳 详情 >
问题:《DOTA2》【7.20E】模式介绍与建筑作用胜利法则·新手指南·3
回答:火车和汽车针对身高在1米2以下的儿童免票,身高在1米2至1米5之间的儿童购买半票。 详情 >
问题:有点意思啊,这守望先锋自定义模式。
回答:还在吗,有事找你 详情 >
评论 (0)
