前言
- 本文仅供《码农翻身》公众号发布
- 感谢刘欣老师的指点、修改和排版
1.背景
1978年,Java帝国张家村新一任村长谋权篡位成功,他废弃20多秒的闭关锁村政策。从此,张家村从封闭走向开放,并与村外世界逐渐接触。也因此,陆陆续续有一些年轻人走出村庄,前往更大的舞台一展身手。
事情就发生在与村外的收寄信上…
2.信使
我是SMSContext,中文名叫信使。自从张家村改革开放以来,我便在村里负责张家村和外面各大村落的通讯工作。
张二妮每天都往我这里跑,每次都说来看望我,但我知道醉翁之意不在酒啊!
因为村里的小张为了研究Duck Typing前往了Ruby帝国(具体可看:小张的Duck Typing&version=12010310&nettype=WIFI&fontScale=100&pass_ticket=aKnCljgU9ca1m%2FcmuCmyv%2FaDVxtblHOOEWhah9ER9AEOwKRBgBPTDWLuy%2FieXyTy)),每隔一段时间便给张二妮写信。
所以张二妮是来我这,其实是想看看有没有小张的来信。
像张二妮这样每天跑来看看有没有来信的人还真不少,我想了想,利用之前小张和FileIO搞出来的接口回调原理,搞一套消息回调机制,这样就不用他们来回跑了,有信的时候我直接通知他们就好了。
|
|
我开放了一个这样的接口,让需要被通知的人实现这个接口,然后往我这边注册就行:
|
|
如果有来信的话,我就调用SMSCallback接口的onMessage方法通知注册者:
|
|
当我想把这套机制推广的时候,我突然意识到我只有一个实例。
因为别的村要把来我们村的信给我,而村里的人又得从我这里取信。
所以我实现了单例设计模式。
而如果有两个人都想往我这注册的时候,第二个注册的人会把第一个覆盖掉。比如张二妮和张小花都想往我这注册:
|
|
而我每次都是
|
|
这样张小花的实例就会把张二妮的实例给覆盖掉。
这样可不行,为了让大家都能接收到通知,我得弄个List来存储注册的人:
|
|
修改之后,每次有新的信息来了,我就遍历这个List,然后进行通知:
|
|
如果注册者判断消息是发给自己的,就进行处理:
|
|
推行了一段时间,从大家的反馈上,效果还不错。
虽然实现起来非常容易,但也呈现了一种思想。
我把这种思想称为”观察者设计模式“。
换个角度来说,就相当于一群人在观察我,如果发现我有新的改变(来信息)就通知他们。
所以我是被观察者,而张二妮她们是观察者。
3.规范
我把这套模式说给别村的信使听,之后,越来越多的村像我们一样搞一套类似的模式来进行信息通知。
但是每个村的实现方式又有点不太一样。比如有的信使他就不用SMSCallback接口,自己搞了个SMSListener的接口,也不用register方法来注册观察者,而是用addObserver来添加观察者。
这样一来,导致我们张二妮她们去别的村又得再实现一个接口,非常不方便。
虽然这件事是我搞出来的,但我无能为力呀,只能上报帝国。
帝国非常重视,派了巡察使下来解决这个问题。
巡察使了解情况之后说,竟然大家都有共性(暴露),那帝国就把他抽象出来。
首先,暴露狂需要继承Observable类,Observable类对外提供了这几个接口:
- 1void addObserver(Observer o),增加观察者
- 1void deleteObserver(Observer o),删除观察者
- 1void setChanged(),设置有事件的标志
- 1void notifyObservers(Object arg),通知观察新的事件
- 1int countObservers(),统计观察者数量
其次,观察者需要观察暴露狂,就要实现Observer接口,Observer接口中有一个待实现的方法:
- 1void update(Observable o, Object arg);
暴露狂每次要暴露消息就会通过调用观察者的void update(Observable o, Object arg)来进行通知,第一个参数是暴露狂自己,第二个参数是暴露狂调用notifyObservers(Object arg)传进去的参数。
我听了之后翻了翻白眼,我们可是为了村民服务,居然说我们是暴露狂…不过,这样一来,大家统一一样的规范,倒是推动了帝国信息传输行业的蒸蒸日上。
为此,我首先对自己进行兼容。
|
|
同时,张二妮她们也进行标准化。
|
|
巡察使还得意地告诉我,他们给这套规范起了个洋气的名字,叫发布-订阅模式,因为这看起来就像一批人去订阅报纸,然后报纸一来就发给订阅的人一样,是一种一对多的关系。
好吧,其实,我的观察者设计模式也很洋气!
4.后续
随着帝国地不断发展,我们通讯行业在观察者设计模式的推动下磕磕碰碰地走过来。
我们遇到了这些问题:
- 随便把一封信发给观察者,让观察者去判断是不是他的,这种做法并不好,因为观察者可以随便看信的内容,所以我们需要一种机制来判断这封信是属于哪个观察者的,然后notify给对应的观察者。
- 把信发给观察者们是一种同步的行为,如果某个观察者在自己的update方法中做了比较耗时的操作,可能会堵塞,以致于后面的观察者迟迟收不到消息,对性能表现堪忧。所以,我们必须设计一种比较合理的异步通知机制。
后来,我还听说有些村庄在网络传输中都采用观察者模式思想。
不管在哪里用,怎么用,符合这种想法的思想都是观察者设计模式的思想。
最后更新: 2017年11月08日 23:59
原始链接: https://xiaoqinyu0000.github.io/2017/03/31/Java/JavaObservable1.0/