自我联想学设计模式(初级版)-1-观察者模式

版权声明:不自见故明;不自是故彰;不自伐故有功;不自矜故长; https://blog.csdn.net/LightUpHeaven/article/details/84673698

如果单纯的看书,其实很容易陷入到各种概念中去,最终导致似乎懂了,但实际开始使用的时候又有各种问题。这个版本的设计模式只从实用来入手,就是在各种情况下,根据联想快速的代入这个模式,能够迅速用起来,转化为代码。所以这个版本的设计模式都以现实中的例子自己联想。

假设我以去电影院看电影为例,因为观察者嘛,就是看东西,所以这里以看电影为例。

这就是观察者的模式了。

这里我们有目标:电影毒液。有观察者:观影者N个。

这就完了吗?该怎么转化为代码呢?

那么我再仔细想想,目标也就是电影毒液。

它是什么?该怎么转化为代码?

假使我现在还不知该转化为代码,我不管那么多我先建立一个类,后续怎么联系起来,后续再看。

于是我先创建一个MovieVeno类。

现在有了Movie类,该怎么和观影者联系起来呢?

假使现在还没有思路,我不管那么多,先建立一个类再说,反正不管是谁都是一个对象嘛!如果建立错了,我可以删掉啊。

如此,便建立起了两个类。

然后呢?这两个类如何建立关联呢?其实在代码里,我们知道,说两个类有关联,就是能互相访问到对方,无论是通过消息传递,或者彼此有对方的引用。

既然如此,我们知道电影院一般都是一个电影多个人看,我们可以给每个人都持有这个电影的引用,也可以给这个电影持有每个人的引用。

这里呢,我通过一些朦朦胧胧的记忆,依稀记得,观察者模式是目标持有观察者的引用。

那么我就让电影持有观影人的引用吧。所谓引用在这里指的就是指针。如果有人有疑问,为什么是指针?那不是指针还能是什么呢?

所以:

在这里我给观影人加了座位编号的属性,给电影加了一个保存观影人引用的map。

这里UML的类图使用聚合关系。意味着观影人可以离开电影单独存在。大家只是因为看这部电影所以才聚在一起的,看完也就散了。

好了目前看起来不错。等等。怎么总感觉哪里怪怪的。

看起来两者似乎关联起来了,但是如果转化为代码呢?MovieVeno只是有了这个map,但是还没有添加的操作啊,我们仔细回想看电影的过程,还有十分钟开场了,你拿着爆米花和可乐,等女友上完洗手间之后,两人入场了。

对!入场啊!怎么表示入场呢。加个函数啊。

哎?仔细看看明明是电影类,怎么有个进入观影室的函数。

对啊,如果你不进入观影室,你站在电影院外面,你在网吧里,怎么看电影?

在现实世界里你和什么产生关联,其实就是触碰嘛!精神触碰,身体触碰,眼神触碰等等。

要看电影就要去电影院。

但在电影类里有你个进入观影室的函数确实有点怪。怎么办?

我们再想想,如果没有灵机一动,恍然大悟,那就什么都不做,继续往下看。

好,现在进入电影院了。电影开场了。我们该看电影了。

可是放在代码里怎么表现呢?首先添加个看电影的函数吧。

这能表现出来么?也表现不出来,因为没有数据表明看哪部电影啊?那上面不是有个箭头表示他们有联系吗?

是啊,但是代码里可没有箭头啊。所以我们还是要把电影的数据给观影者的。

好了,我们开始看电影了。

两个貌似Loser的人击败了两个貌似高手的人。电影结束了。该离场了。

等等,离场怎么表示?添加函数。

到这里是不是该完事了。

看起来,应该完事了,但就是电影类里入场和离场函数有点怪。因为观影室才是我们观影的地方,我们进去和离开的地方也是观影室。

总觉得亏欠了观影室什么那么点东西。

哎,算了,下次再说吧,毕竟代码着急上线。

看完了电影《毒液》之后,电影院的人换片啦,换成张艺谋的《影》,结果发现我们又要新建影片和观察者列表,你会发现,他们播放《影》的地方还是刚刚播放《毒液》的那个观影室,然后还会播放《无双》,那么我们就会发现每播放一次电影,就要新建观察者列表,但如果不考虑效率,也并不是不可以。

但是我们还是会发现之前一直让我们奇怪的地方,因为我们观察的是电影没错,可是我们没有在代码里表现出观影室这个事物,也即是说,从代码里其实我们很可能是在露天观影。其实即使是露天观影,我们的信息也不足,因为全世界露天的地方太多了,能播放电影的地方何止一个?更何况很明显我们不是,我们就是在中影电影院的观影室里看的。

所以不能忽视这个观影室,现在我们有加个观影室类。

现在多了一个类,我们要把这个电影和这个观影室关联起来,怎么关联起来,因为我们看的这部电影就是在这个观影室里放的,所以我们把它放入这个观影室里,让他通过这种最简单的方式关联起来。而且,观影室里的电影是会不断更换的,所以我们用当前的电影来表示正在播放或者说观影者正在观看的电影。

电影的内容虽然不同,但是存放的介质,有片头和片尾,被广电总局审核通过,等等都是有统一标准的,换成代码也就是有统一接口的。观影室不能只放这一部电影,而是满足这个条件的都可以播放,所以再改代码。

同样,观影者也不是只能看《毒液》这一部,任何电影都可以看。所以,再改代码。

现在我们再看一下,其实就会发现,之前的在电影类里有入场和出场函数为什么奇怪了。

我们再改代码:

而显然,能够进入的玩家都是进入的观影室,而且观影室的位置也决定了观影者的数目上限,这和放什么电影没关系。

再改代码。

到这里我们就会发现,其实我们和电影本身并没有什么关系,我们看到的只是电影的内容,但是电影的播放,什么时候播放,在哪里播放都不是我们控制的了的,我们只是进入那个观影室坐在座位上等待而已。那个观影室放了什么电影,我们就看的是什么电影,放了《毒液》我们就看毒液,即使我们买的是《毒液》的票,可如果对方放的是《影》,我们其实长露出看不了毒液的。

所以我们应该和观影室联系起来,当观影室切换电影时,我们收到通知,进去看它马上要播放的电影就行了。

再改代码。

这样,我们再加一个切换影片和通知观影者入场观看影片的函数。

当观影室ChangeMovie的时候,调用自己的Notify函数,因为观影室的wMap里有每个观影者的引用,所以遍历wMap,调用每个观影者的WatchMovie把当前切换的影片传给他们,他们就可以看了。

我们发现,其实代码描述的就是现实生活中的事,没有什么新鲜的东西,用生活中类比的话,我们就可以把这个模式类比出来。

一个观察的目标类,目标里有观察者的引用列表有添加观察者和删除观察者的函数有更新自己数据的函数有通知观察者更新数据的函数。

一个观察者类,有更新自己数据的函数。在被通知更新时调用。

这就是观察者。

猜你喜欢

转载自blog.csdn.net/LightUpHeaven/article/details/84673698