Chinaunix首页 | 论坛 | 博客
  • 博客访问: 165160
  • 博文数量: 56
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 14
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-24 17:36
文章分类

全部博文(56)

文章存档

2016年(43)

2015年(9)

2014年(2)

2013年(2)

我的朋友

分类: C/C++

2016-02-02 16:41:30

作者:gfree.wind@gmail.com
博客:blog.focus-linux.net      linuxfocus.blog.chinaunix.net

今天学习观察者模式。

观察者模式的定义:观察者模式定义了对象之间的一对多以来, 这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

观察者模式应用很广泛。在Linux内核中的notifier chain即可看作是观察者模式。那么下面就看看notifier chain的如何实现的观察者模式。

kernel中有很多模块都需要了解网络接口的状态,这时就是观察者模式大显身手的时候了。这里,网络接口就是观察者模式中的subject,而需要了解其状态变化的其它模块,即为设计模式中的observer。当网络接口状态发生变化时,由接口主动通知所有observer。对于网络接口来说,它不知道observer是谁,对于状态变化observer如何处理,它所要做的就是将状态变化信息通知observer。而observer可以任意加入或者离开subject,对于它来说,这个是自由的。它只需告诉subject,现在我要关心你的状态,有情况通知我。而离开时,则通知subject,不要再发消息给我。

下面就以网络接口状态这一情况,来说明一下kernel中的notifier chain是如何实现的。
首先需要为网络接口定义一个notifier head。
  1. static RAW_NOTIFIER_HEAD(netdev_chain);
其类型很简单
  1. struct raw_notifier_head {
  2.     struct notifier_block __rcu *head;
  3. };
只是一个struct notifier_block的头结点。
节点的具体结构:
  1. struct notifier_block {
  2.     int (*notifier_call)(struct notifier_block *, unsigned long, void *);
  3.     struct notifier_block __rcu *next;
  4.     int priority;
  5. };
从这个struct notifier_block可以看出,其为一个优先级单链表,而notifier_call为observer的回调函数。即观察者模式中observer的处理事件的函数。

以ARP模块为例,在ARP模块的初始化函数中arp_init中,它通过调用register_netdevice_notifier表示它对网络接口这个subject感兴趣,通过比较优先级,将arp_netdev_notifier作为一个节点挂在了netdev_chain的链表上。

那么当网络接口状态发生变化时,如网络接口变为UP状态时,就通过call_netdevice_notifiers(NETDEV_PRE_UP, dev);通知所有注册的observer,某个dev的发生NETDEV_PRE_UP的状态变化。

因为今天主要说的是设计模式,而非notifier chain的实现,所有具体代码还是请参考linux代码。这部分代码很简单,比较容易看懂。


Note:
对于设计模式,我一直认为不要去生搬硬套的去使用设计模式,更无需去记住哪个模式的名字是什么,特性是什么。无论是什么语言,我们只需记住封装变化,保持灵活。设计模式要信手拈来,领会思想,灵活使用。

参考:
1. 《设计模式——可复用面向对象软件的基础》
2. 《Head First 设计模式》


阅读(1137) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~