观察者模式与依赖反转原则
最近写了一个“休息吧,程序员”的小工具,用到了观察者模式,感觉自己的理解还不够深入,借此机会稍微深入学习一下。
项目介绍:提醒程序员不要过度工作的一个脚本,暖心程序跟你道晚安,使用观察者模式实现,我把它叫做:休息吧,程序员!
po图
项目地址:https://github.com/cooljacket/relax_please
先po一下我实现出来的效果图(注意桌面右上角):
暖心跟你道晚安~
如老妈一般的监督你不要过劳!
项目设计
首先说下这个项目的组成:
1. 监听器:监听系统的键盘输入、系统时间
2. 发送提醒:一旦监听的事件发生(比如超过11点,该睡觉了),那么监听器就会触发这个“发送提醒器”,提醒器会以某种方式发送通知给使用者
这样看来,这个项目的对象关系是一个很经典的“观察者模式”的模型,下面先看一下我画的UML图:
看不懂UML图的朋友也没关系,稍微解释一下就知道了:
1. 监听器抽象接口Listener,它实现了所有监听器共有的功能,即绑定观察者,解绑观察者,(在所监听的事件发生的时候)通知所有绑定的观察者,以及监听事件。
2. 我需要监听两个事件,一个是使用电脑的情况(通过键盘输入来估计),一个是当前的工作时间(看看是否有熬夜),所以继承实现了两个具体的监听器,KeyBoardListener和SayGoodNightListener,它们都只需要实现listening函数即可,因为其它的都在抽象类Listener中实现好了!
3. 观察者抽象类Observer,这个其实只是个接口而已,不是一个类,因为update()虽然是共有的接口函数,但它的实体是因人而异的,没法在这个类里给出一个default的实现(对比一下Listener的notify方法就知道了)。
4. 目前的发通知给使用者,只实现了一种方式:发送泡泡弹窗到桌面右上角,所以只写了一个NotifySendObserver类。
值得注意的是:一个监听器可以有多个观察者,而一般一个观察者只能有一个监听器。比如监听是否熬夜这个事件,可以有多种通知方式,比如响闹铃,发送泡泡弹窗到桌面的右上角,记录熬夜情况到日志文件以备后续分析,等等。而一般一个观察者都是特化了的,不会用在多个监听器上面,比如你熬夜的时候响一段“睡吧睡吧我亲爱滴宝贝……”的摇篮曲,是针对特定的这个(熬夜)事件的!
什么是观察者模式?
引用一段话1来描述:
建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。
注意这里,观察者并不是真的去观察,而是被观察目标通知才会得知有事件发生的!
这是一个事件驱动模型,不直接想它的好处,先反过来想,如果不这样做,而是让NotifySendObserver主动去询问/检测事件有无发生,这样的话,得设置好去检测的时间间隔,除非不停去检测,否则肯定是有概率会错过一些事件的。忙死忙活,吃力不讨好^_^(手动微笑)。
而观察者模式正是把检测事件和响应事件这两个职责给分离了,各司其职。我这边自己监视使用者有没有熬夜,有的话,我就通过接口告诉你,你再发通知给使用者,叫ta赶紧睡觉。没有发通知给你,你也不用来问我,就是没事情发生,各自清闲~
再举个简单的例子,就是我们平时按手机app里的按钮,那个应用内部肯定不会时刻去检测这个按钮有没有被按下,而是按钮被按下的时候,系统会发送一个消息给应用去处理。
Why抽象接口?
有人可能会说,哎,你怎么要搞这么麻烦啊,无论是监听器,还是观察者,都要抽象出一个接口出来?
这里安利一个我自己到现在还没懂透的“面向对象五大原则SOLID”:
参考维基百科:https://zh.wikipedia.org/wiki/SOLID_(%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E8%AE%BE%E8%AE%A1)
这里很明显运用的就是D,依赖反转原则。
问题还是回来了,用了有什么好处呢?不用,又有什么坏处呢?
这里推荐一篇关于依赖倒转原则的好文章,里边的“妈妈讲故事”的例子很鲜明地体现了这个原则的好处:高层模块可以自由选择底层模块,耦合性很低。
说人话,就是,在这个例子中,如果我不抽象一个Observer接口的话,那么Listener(高层模块)就直接依赖NotifySendObserver(底层模块)了,那如果我后续不想用这种通知方式,而是想改用音乐作为闹铃,是不是除了写多一个MusicObserver类,还要改动Listener类呢?
有人可能会说,这在python里都一样,因为每次运行都是重新编译,那试问一下,如果你是公开发布的一个东西,还能这么做吗?如果不是用python而是C++、Java之类的静态语言呢?
嗯,抽象接口的好处就是这样了。
而Listener作为一个抽象类,则不是同样的想法了。我想实现多个监听器类,它们有很鲜明的公共逻辑,比如上面的KeyBoardListener和SayGoodNightListener,那这个时候主要是继承重用的想法,而不是为了要依赖反转。
- http://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/observer.html ↩
观察者模式与依赖反转原则相关推荐
- 【简译】关于依赖反转原则、控制反转和依赖注入的抽象的初学者指南
原文在此. ======================================分割线==================================== 介绍 文章以介绍依赖反转原则开始 ...
- 依赖反转原则DIP 与使用了Repository模式的asp.net core项目结构
DIP 依赖反转原则 Dependency Inversion Principle 的定义如下: 高级别的模块不应该依赖于低级别的模块, 他们都应该依赖于抽象. 假设Controller依赖于Repo ...
- 依赖反转原则(DIP)
依赖反转原则.依赖反转原则的英文翻译是 Dependency Inversion Principle,缩写为 DIP.中文翻译有时候也叫依赖倒置原则. 为了追本溯源,我先给出这条原则最原汁原味的英文描 ...
- DIP依赖反转原则——实现松耦合的设计
在<IoC控制反转设计原则--实现松耦合>我们将控制工作委派给其他类来完成,向松耦合设计又迈进了一步.但是我们类仍然依赖着具体的类,所以我们可以使用DIP(依赖反转原则)来进一步获得松耦合 ...
- 地表最强22个互联网定律和原则:炒作周期、依赖反转原则、Spotify模型……
▲ 点击上方"老于的笔记"关注公众号 回复1,免费获取B端运营地图 正文来了 精选了7个原则和15个定律,互联网人公认的牛出天际! 产品经理照着做策划,保证怼开发.怼测试.怼老板, ...
- 依赖反转(倒置)原则(Dependency inversion principle,DIP)
在软件设计.编码过程中有几个基本原则即SOLID原则,学习理解能够帮忙我们写出更健壮的代码.SOLID是五个基本原则的首字母.这五个原则如下: Single responsibility Open–c ...
- 单一原则,开放-封闭原则,依赖反转,里氏族替换原则
读书笔记:大话设计模式 单一职责原则 单一职责原则(SRP):就一个类而言,应该仅有一个引起它变化的原因 例子 一个俄罗斯方块游戏设计思路 其中游戏业务逻辑: 数据的每一项值变化的问题,下落,旋转,碰 ...
- 13. 设计模式之反转原则:如何减少代码间的相互影响?
一.DIP:统一代码交互的标准 在上一讲中,我们学习了 SOLID 五大设计原则,了解了在实际工作中应该如何有针对性地使用这些原则.不过,其中有一个原则,可能是你用得很熟练,但是说到概念却又容易跟其他 ...
- Java依赖于抽象不依赖于具体,依赖倒置原则(Dependecy-Inversion Principle)
依赖倒置原则(Dependence Inversion Principle,DIP)的原始定义: 高层模块不应该依赖底层模块,两者都应该依赖其抽象: 抽象不应该依赖细节: 细节应该依赖抽象. 抽象:即 ...
最新文章
- 雷林鹏分享:jQuery EasyUI 数据网格 - 创建属性网格
- makefile ifneq多个判断条件_一文入门Makefile
- 415. Add Strings
- 如何基于Spark进行用户画像?
- php datetime 对象,PHP DateTime 对象和 Date 函数的 Demo
- color 的一些处理
- php oci8 11,Linux下PHP5.2 Oracle客户端扩展(OCI8)安装
- pyqt5 列表内添加按钮
- Oracle开源Fn,加入Serverless之争
- paypal 支付接口 php,PHP整合PayPal支付
- linux 强制结束任务管理器,结束拒绝访问的进程 cmd下结束进程 强行结束进程
- app下载 微信扫码打开 提示用户用浏览器打开
- itest听力答案2020_大学英语itest2018答案
- 计算机网络八大性能指标
- java emoji表情_java处理emoji表情的方法
- 《Redis设计与实现》学习笔记
- k8s 安装nfs_kubernetes挂载nfs报错 | 运维笔记
- 微信分销商城如何保持客户粘性
- 教你使用 Python 获取美国重要经济指标数据
- ChatGPT一路狂飙,对于教培机构是危险还是机遇?