观察者模式
组件间通信,我会优先使用路由的通信方式(iOS中需要用到 runtime,Android 中需要用到反射和注解),组件之间按照路由协议(类似 url)实现各自的职责即可,组件间的松耦合性增强了软件设计的弹性和高可用性。
路由结合观察者模式,可以让你的组件设计更上一层楼。路由可以解决单向调用的问题,让组件之间无需知道对方是否存在。观察者模式可以让调用者(使用你框架的)可以很方便的知道组件的内部事件。
武林至尊,宝刀屠龙,号令天下,莫敢不从,倚天不出,谁与争锋?
在说观察者模式之前,先介绍一下 iOS 中的代理(delegate).
代理 delegate
在 iOS 中,代理(delegate)的本质是 protocol,类似 java 中的 Interface,一般用来处理 一对一
的关系,如下图所示:
下面的例子模拟了调用和实现过程,使用 Bank
对象和 BankDelegate
代理来模拟这种模式。Bank
有变动的时候,通过 notifyAccount
来授权 onAccountChanged
通知用户。
BankDelegate.h
1 | @protocol BankDelegate <NSObject> |
Bank.h
1 | @interface Bank : NSObject |
Bank.m
1 | @implementation Bank |
使用者实现 delegate
1 | - (void)viewDidLoad |
当然,delegate 也可以做到 一对多
,改造一下 Bank
就可以实现。
1 | @interface Bank : NSObject |
Bank
内部使用数组将 addBankDelegate
得到的 delegate
存起来,notifyAccount
中就可以进行通知了。
1 | Bank *bank = [Bank new]; |
观察者模式
理解了 delegate,观察者模式就很好理解了。
当一个对象改变状态时,它的所有依赖着都会收到通知并自动更新,这是观察者模式的常规定义。
观察者模式是一种 一对多
的设计模式,如下图所示:
继续上面的例子,使用 Bank
对象和 BankDelegate
来模拟这种模式,Bank
有变动的时候,通过 notifyAccount
来授权 onAccountChanged
通知所有注册了 BankDelegate
的用户。
Talk is cheap. Show me the code
BankDelegate.h
1 | @protocol BankDelegate <NSObject> |
Bank.h
1 | @interface Bank : NSObject |
Bank.m
1 | - (void)notifyAccount |
调用者
1 | - (void)viewDidLoad |
看到这里,你应该发现 delegate 的设计其实就是观察者的一种设计手段而已,它本身也是观察者模式。
在 iOS 中,除了 delegate,还有很多这种设计模式的体现,如 KVO、Notification、Observer、Block 等。
发布-订阅模式
观察者模式中观察者对被观察者(Bank)是有感知的,至少需要实现对应的 BankDelegate
,二者之间还是是有一定的耦合度。
那么,有没有一种方法再来降低这种耦合,让双方都不用去关心对方的存在呢?发布-订阅模式是一个不错的选择。
发布-订阅本质也是观察者模式,但是他更加的松耦合,发布者和订阅者都不用清楚对方,全部由订阅中心做处理,这样耦合度就几乎没有了。
如图展示发布-订阅模式:
在 iOS 中,Notification 就是发布-订阅模式的一种实现,NSNotificationCenter 就类似订阅中心。
1 | // 发布 |
争论
网上有很多人说,观察者模式和发布-订阅模式是两种不同的设计模式,它们压根就是两码事,不能混为一谈。也有很多人说,两者其实都是观察者模式,只是实现手段有点不一样罢了,本质是一样的。
江湖纷争,众说纷纭!
设计模式是一种设计思想,在观察者模式基础上你可以衍生更多的设计模式和更多的设计思想。模式的实现手段可以多样化,没有最好只有更好,就好比 MVC、MVP、MVVM 等,你说它们是设计模式也好,是设计思路也罢,关键是利用它们有没有解决业务需求,为了模式而模式的设计华而不实!
个人觉得,发布-订阅模式只是观察者模式的一种实现手段,它本质还是观察者模式。
扫码关注,期待与你的交流~