1. 模式理解
对于被观察者,当(数据或者是其它的)发生改变时,去通知观察者,以便于观察者在此时作出相应的改变
2. 解决一个什么样的问题
假设要实现:对象A改变的时候通知对象B也改变。
-
实现1:在A中持有B的引用,在A改变的位置调用B的相关方法。
分析:这种写法首先存在极高的耦合性,A和B紧紧的关联在一起,并且如果有一天不需要这种改变关系或者B有所改变,那么很容易影响到A,这与扩展性原则严重相悖。其次B的实例在A中获取很困难,在实际开发中有很多这种情况。
那么这时候就要请出一句非常牛的话:
没有什么问题是加一个中间层解决不了的,如果有,那就加两个!—— 鲁迅(XD)
-
实现2:通过一个第三方的被观察者Observable(简称OB)和观察者Observer(简称OV)接口,将A和B隔离开。
其中OB抽象出通知的动作,OV抽象出更新的动作,A实现通知,而B则实现更新。
当需要通知——>更新这种关系时,为A注册(依赖)OV,此时A不直接持有B的引用,而是持有OV的引用,这样当A发生变化时,调用A的通知方法,进而调用OV的更新方法来使B改变
分析:通过中间层OB和OV,将A和B的直接依赖关系消除,这样即使B换成C也不会有任何影响,并且因为A依赖的是OV因此很容易扩展实现为一对多的关系,
总结下来就是:对一个被依赖对象和一个或多个依赖对象进行解耦,以达到在被依赖对象变化时依赖对象能够收到通知以作出更新
3. 案例
这里举一个简单的例子:当数据发生变化时,通知TextView的显示更新。通常数据被包装在实体类中,并且由get/set方法提供访问。
有几个问题需要解决:
(1)TextView暴露的只有setText()方法并且没有直接实现Observer。
(2)当有多个数据和多个TextView时,如何保证数据和相应的TextView是绑定的。
解决思路:
(1)对于第一个问题,我们显然不可能为此去特意改写系统类,那么为了解决这个矛盾,就需要引入另一个设计模式:适配器模式(下一篇文章)。简单的说就是包上一层外衣,因为我们最终的目的是获取到一个OV角色,为此我们需要一个实现OV角色的对象,姑且称之为OVI(ObserverImplementation),在这个对象中我们持有TextView的实例,这样就伪装成了一个TextView,然后提供onChanged()方法来响应变化。
(2)对于第二个问题,就需要一个新的中间层UIBus(实现OB的功能)。在UIBus中,持有一个Map<tag,Observer>,用来记录绑定关系(唯一性的tag和OB),使用register()在OV的构造方法中为自己注册;同时我们提供一个postNewData(tag,data)的方法,在这个方法中,我们做的事情就是从Map中查找指定的tag,获取到OB,如果没有找到就先存入,然后调用OB.onChanged()
(3)在解决这两个问题后,只需要在set方法中调用UIBus.getDefault().postNewData()。则在任何地方数据更新时都会使TextView变化。
网友评论