模式名称
- SAD, Simple API for Datagram
意图
- 分离网络报文的解析和处理, 使解析代码和处理代码不再耦合在一起, 便于扩展. 类似SAX(Simple API for XML)将XML文档的解析和处理分离到不同的单元中
动机
在网络通信软件的开发中, 经常要处理网络上接收到的各种数据报文. 而收到某种报文后, 需要进行的处理逻辑上可能不止一件事情. 处理过程中会用到报文中的数据, 因此需要对报文进行解析. 而报文的结构通常存在动态部分, 而在C语言中, 无法定义一个数据结构可以直接将报文映射到该结构. 参见<<Navigator Pattern: 导航者模式>>
缺乏考虑的做法通常会把解析和处理放在一起, 一个大函数, 用局部变量甚至全局变量来保存解析出来的数据, 并对其进行各种处理. 这样做的问题是:
- 难以扩展: 当需要增加新的处理时, 需要在解析过程中多个地方插入处理代码
- 难以理解: 不同的处理代码混在一起, 和报文解析的逻辑也混在一起, 难以看清楚真正做了什么事
- 容易出错: 不同的处理共享解析出来的数据, 容易互相影响, 引入错误
另外一种常见的做法是每种不同的处理单独去解析自己需要的内容. 这种方式相对内聚, 但需要解析多遍报文结构, 解析代码也有重复
我们需要更好的设计.
方案
SAX以事件驱动的方式分离了XML文档的解析和处理. 我们可以借鉴. 报文有内部结构, 我们可以使用Navigator模式遍历其内部结构, 并在每一个独立的净荷开始和结束时触发回调, 而对报文内容的各种处理可以以回调函数的形式注册到解析过程中, 为每种处理编写单独的回调函数.
例如, 对于Navigator模式中定义的报文结构, 可以定义如下的API:
typedef void (*MessageHandler)(Message*); typedef void (*TopLevelPayloadHandler)(TopLevelPayload*); typedef void (*SecondLevelPayloadHandler)(SecondLevelPayload*); typedef struct Handler { MessageHandler start_handle_message; MessageHandler end_handle_message; TopLevelPayloadHandler start_handle_toplevel_payload; TopLevelPayloadHandler end_handle_toplevel_payload; SecondLevelPayloadHandler start_handle_secondlevel_payload; SecondLevelPayloadHandler end_handle_secondlevel_payload; } Handler; void parse(Message* message, Handler* handlers, int handler_count) { for(int i=0; istart_handle_message(message); } //遍历Message内部嵌套的payload, 并调用对应的handler, 比如: //handlers[i]->start_handle_toplevel_payload(toplevel_payload_pointer); //handlers[i]->end_handle_toplevel_payload(toplevel_payload_pointer); for(int i=0; i end_handle_message(message); } }
而每种不同的处理, 只需提供自己的handler即可. 比如可以有打印报文内容的handler, 有根据报文操作硬件的handler, 有持久化报文数据的handler等:
Handler handlers[3] = { DataPrinter, HardwareManipulator, DataPersister}; parse(message, handlers, sizeof(handlers)/sizeof(handlers[0]));
效果
- 报文解析和报文处理的代码彻底分开, 不再纠缠在一起
- 可以很容易的扩展新的报文处理逻辑
- 报文只需解析一遍
- 其约束在于不同的handler之间不应该有依赖
相关模式
- SAX是处理XML的一种类似的模式, 但其最初的出发点是源于DOM的性能太差, 不过它也有分离解析和处理的效果
- Visitor模式用于在不改变层次结构的情况下增加对这个层次结构的处理, 并且自动分发正确的处理到正确的节点. 它客观上也分离了数据的解析和对数据的处理.