NSNotification Hell

今天我要把 Cocoa Pattern 中的通知中心 (NSNotificationCenter) 给批判一番。不对,应该是说把滥用通知中心的行为给批判一番。

Cocoa 中常用的对象之间交互的方式有这么几种:

  1. Target-Action
  2. Delegate
  3. Callback
  4. Notification
  5. KVO

其中只有 Notification 和 KVO 是一对多的交互方式,而 Notification 是松耦合的 (Loose Coupling),意味着通知的发送者和接收者可以不知道对方。

一般情况下 Notification 用于单向通信(其实也可以双向啊,在 userinfo 里带上发送者就可以了,不过这是一个 bad idea)。双向通信常用 Delegate 和 Callback。

先说 Notification 的好处,它可以用极少的代码就实现两个对象间的信息传递,耦合度最低。相反 Delegate 就要写相当多的代码,而且耦合度比通知中心高。但谁说耦合度低就是好的呢?上学的时候我们就听过一句著名的准则: 高内聚,低耦合。可是有的同学没有理解这句话,一味地追求抽象,解耦,这一方面加大了你自己的工作量,另一方面又使代码不容易维护。 简单的说,这句话就是要我们写的代码单个模块内的元素紧密结合,而不同模块间相互独立。这一点系统自带的那些通知就做的非常好,比如 Keyboard 相关的通知,UIApplication 状态变化相关的通知,这些就跟我们应用的逻辑是完全不同的模块,用通知就是最佳选择了。

Notification 的坏处就是不好掌握程序的走向,当看到某个类的实现里 Post 或者 Listen 某个通知的时候,你需要全局搜索这个通知的 Key, 去看这个通知到底在哪些地方发出,哪些地方监听。这无疑地加大了代码阅读者的工作成本。我在一些项目里全局搜索很多通知的 Key, 发现发通知和监听通知的就只有一个地方,也就是说,明明是一对一的关系,也要飞出一个通知。有些项目随便一个 ViewController 都是监听十几个甚至二十几个的通知,简直无法直视。而我通过阅读代码发现,大多数的逻辑都是可以用 Delegate 或者 Callback 来解决。为了加强代码的可读性和把握程序的流程,多写一些代码又怎么样呢?

最后给出几个正确使用 Notification 的建议:

  1. 只有 1 对多关系的时候再考虑通知中心,不然程序的流程极难掌握
  2. Notification 的 Key 声明在发送者这个类里面,不要全部放到什么 CommonConstant.h 类似的文件里面
  3. 熟悉系统自带的 Notification,不要发跟系统重复的通知
comments powered by Disqus