ngx_io会在相应的ngx_os_specific_init方法中,来策略性的选择到底使用哪个实现。客户代码只需要简单的调用ngx_io中的方法即可。
adapter模式:
上图中,ngx_os_aio适配了原生的异步IO接口,这样,用户代码仍然像以前一样,只要直接使用ngx_io中的五个接口方法,当nginx的IO部分支持linux aio后,用户代码不需要修改。
由于UML本就是针对OO语言的,所以以上我画的类图都比较牵强,什么是继承?什么是聚合?在C语言中,往往都是通过几个函数指针,或者void*指针实现各种封装和多态。没有什么语法上的关联,我就只能从代码意图中来判断了。而代码意图这个比较虚,因为不同的角度理解出来都不一样,所以这个确实不好画。太灵活了点,我只能从一个便于说明的角度来看,例如:上面的ngx_devpoll_module其实就是一个ngx_module_t,呵呵,但是,实际上它最关心的是ngx_event_actions_t的实现,如果完全根据语法来看,根本说不通的。但从代码意图中看,这些module并不关心ngx_module_t,所以我认为,它们只是在实现ngx_event_module_t了。

设计模式就是通过封装变化来解耦,所以,我们先要找出网络IO操作的变化点来。nginx是跨平台的,它会支持linux、freebsd、solaris等操作系统,而每个操作系统的网络IO操作是不同的,这就是变化点了。
客观的说,C语言确实在封装上很差,就像nginx,如果我们要开发一个处理http协议的module嵌入进nginx进程,必须了解ngx_http_module里到底做了什么,真没隐藏啥细节,module开发者们表示很郁闷,传奇私服装备补丁。上面的这些设计模式,只是做到了代码上的解藕。如果nginx用C++写的话,我相信,现在第三方module都能数以万计了。
这个模式用以适配接口,通常都是我们已经定义好一种接口了,有一个新的实现却有着不同的接口,接下来adapter就开始发力了。下面我们仍然以nginx对网络IO操作的封装部分来看。
linux平台下可能存在普通的IO或者异步IO方式。我们在最初已经封装好ngx_os_io_t接口了,客户代码都是这么直接使用的。现在linux实现了异步IO,而它的调用方式与普通的读写IO接口完全不同,所以,如果要支持aoi就需要一层adapter来适配ngx_os_io_t,这就是adapter方式了。
挑战时我就木有敢挑战;就看不懂代码;有木有一点的思路;怎能写出好的数据;结束时看到分到的房间第三题都木有做出来的;以后要加强练习啊;以后要在Topcoder上面混啦;一定要写好类啊;学好C++;看组合数学,数论;
为什吗会写这么一篇文章那,因为昨天晚上我们四个人第一次参加TopcoderSRM赛,结果不用想自然是很杯具的,首先,我们是业余级别的,而且还是菜鸟级的我们,,更加称不上是Topcoder,我们也是刚刚搞ACM,而且实力很弱;昨天我们队里面的琴姐过生日,说好八点开始的,匡匡和蓓蓓他们去买生日蛋糕回来有点晚,所以耽误了一会,wwww.3000ok.com;快九点我们开始生日庆祝的;博文给老大打的电话让他也过来啦;因为几天晚上原来定的是要开会的;刚好要给琴姐过生日;又加上我们要比赛;真是皆大欢喜;Jie,Yang让Jie Qin说两句明显JieQin很是激动,感觉大家都很忙能抽出时间给她过生日很是激动;她说到这时我也感觉到大家一直都很忙,忙于自己的事情,无暇停驻小憩一会,感觉大家很累的;大家刚开始分蛋糕;吃的很highing;恶作剧开始上演啦,突然匡匡先向老大脸上摸了一下,这时我也出手了;顿时大家都忙了起来;这时数我最活跃,结果可想而知;群起而攻Me;快到结束马上十点时老大让我们过去准备;因为比赛是晚上十二点开始;老大买了几包方便面;半夜一人弄了一包,私服传奇;我是木有吃下去;让匡匡吃了;我们一行人来到老大他们网站参加的比赛;赛前开始往他们电脑上装Java运行环境;因为Topcoder客户端是
用Java做的所以就先下了,接下来又是安装插件,又是安装编译器;最让我无语就是编译器;我让匡匡给我传个VC6.0结果安装的过程中,需要重启系统;关键是菊花的电脑安了冰点,重启时距开始比赛还有10分钟,自然是相当的紧张,第一次就是这么的不顺;疯狂的下载客户端;插件就没木有再按啦;实力很弱啊,第一题很快读懂题意啦;就是不知道该怎么做;就木有一点思路;开始看第二题时;已经有点晕晕忽忽的啦;第三题直接木有看;
bridge桥模式:
这里有五个函数指针(*_pt都是函数指针)和一个变量,用于收发网络数据,我把它理解为OO中的abstract class(每个ngx_os_io_t定义的变量都会重新实现这五个函数)。
所以,nginx首先定义了ngx_os_io_t来封装这些变化。
nginx自己用时,是以ngx_module_t中的type成员来决定使用哪个实现的。目前的nginx代码中,如果用了一种接口就一定会指定相应的type。可是实际上,这也可以用来展示桥模式。以事件module为例来看看:

拥有函数指针的struct,我通常认为它们是OO中的abstract class,实现它们的文件(一堆函数)要对应到OO上,我则喜欢把它们当做子类来看。对于void*这样的成员,要根据意图来看了,通常我会转换成聚合加继承的关系。
是这样吗?设计模式的概念是从建筑领域引入的,本身从没歧视过面向过程编程语言,它只是对一类问题的普遍解决方案而已,zhaosf.com。面向对象语言因为有类、多态等特点,使得开发者们容易达到:隐藏细节、封装变化,而这与设计模式的目的比较一致,所以大师们爱把设计模式与面向对象语言二位一体的使用。然而,存在即合理,C语言直到今日仍然在大型软件工程中担纲主角,其种种设计方法其实与我们通常见到的设计模式本质是相同的。例如nginx这个纯C语言写就的的高性能WEB服务器,就有许多地方使用到了传奇私服面书籍提到的设计模式。下面通过nginx源码来看看C语言是怎么做的。当然,UML图都是我根据代码意图所画,并不准确(C语言真没法画UML),只用于方便理解,呵呵。
nginx是以module的概念贯穿始终的。它有一个基本的抽象层ngx_core_module_t(从意图上判断,context有抽象接口的功能,虽然简单从语法上看不出)。然后,nginx module有三个基本类型,分别是event(处理各种事件模型,如epoll/select等),http(处理各种http协议的事件),mail(处理mail相关的事件)。针对每种类型的module,都有许多个实现,比如event module就有9个实现,这里的每个实现其实也是个子类。
当然以上只是一家之言,不必当真,如果对nginx源码有研究的话,欢迎各位拍砖。