切换和提供程序






4.58/5 (9投票s)
一种基于发布/订阅消息传递并扩展以支持自定义提供者的通信架构模式。
- 下载源代码 - 586 KB(原始)
- 下载带示例的源代码 - 594 KB(更新)
- 下载源代码 - 20.1 KB(已移除可选依赖项)
引言
开关与提供者是一种基于发布/订阅消息传递的通信架构模式,并扩展了自定义提供者。核心的发布/订阅消息传递系统称为开关(Switch)。提供者(Provider),或生成和消费消息的接口适配器,被实现为与特定协议或技术进行接口,并将其连接到开关。
开关与提供者模式主要旨在解决为软件系统提供外部接口的问题,这些接口的规范可能会随时间变化。内部软件组件(位于主应用程序域内的组件)应直接使用开关(最好通过接口和依赖注入),而外部组件(位于远程应用程序域内的组件)则通过提供者进行通信。尽管该模式解决了外部接口问题,但它同样适用于内部组件之间的接口适配。
该模式非常适合解耦组件之间通信方法的细节,从而使组件的实现细节与通信方法的实现完全隔离。例如,一个提供基于 UDP 数据包的外部接口的组件,可以将数据包的处理抽象为一个提供者,该提供者根据数据包中的数据创建消息;然后消息被传递给开关,开关将消息分发给已订阅的组件。
设计
Switch
开关是开关与提供者模式中的核心组件。尽管此模式的关键概念不需要开关的特定实现,但此处描述的实现被认为是后续讨论该模式优势的基础。
开关中的订阅机制实现为一个树,其中每个节点可以有任意数量的子节点。每个节点包含一个唯一的规则、一组要通知的订阅者以及一组子节点。
当使用开关发送消息时,会处理树中的节点,以识别消息是否通过该节点规则的测试。如果测试通过,则保留订阅以进行通知的处理程序,稍后调用,并处理子节点。如果测试失败,则忽略处理程序和子节点。搜索完树后,通过调用在搜索过程中识别的处理程序来传递消息。
规则
开关的订阅机制依赖于规则和规则链,订阅由处理程序委托和规则链定义,规则链决定是否应为任何特定消息通知处理程序。
规则是简单的测试,用于检查消息并确定消息通过或失败。规则应使用最少指令的简单测试创建。例如,一个有用的规则是测试消息类型是否与所提供的目标类型匹配。如果订阅关注的是所有 AddMessage 类型的消息,那么 IsTypeRule 规则将是识别这些消息的理想选择。
规则链是一组按顺序测试的规则,用于基于简单部分指定更复杂的测试。在定义订阅方面,规则链是规则的有序列表、数组或其他集合,所有规则都必须通过,才能将消息通知订阅处理程序。在订阅树方面,规则链通过标识到订阅处理程序路径中每个节点处的规则而存在。在以下示例树中,使用规则链 A-C 定义的订阅会将关联的处理程序放置在包含规则 C 的节点处。
每个订阅的规则链都应经过选择,使得消除最大可能不需要消息集的、最简单的规则位于链的第一位,后续规则也类似排序。这种选择规则链的方法将确保订阅树以最佳方式执行。
提供者
提供者建立在适配器模式之上,在需要自定义接口的每个点实现。在应用程序接收包含可重构为消息的数据的 UDP 数据包的情况下,自定义提供者负责将数据组装成消息,然后将其交给开关。
例如,当需要提供自定义接口(例如通过 WS-* 接口访问应用程序)时,提供者是基于 RPC 的接口到基于消息的接口的适配器。如果该 Web 服务 API 包含一个 Add
方法,则提供者将通过创建 Add 消息并通过开关传递来实施 Add
方法。
一个简单的通用提供者,它将开关的接口暴露为 WS-* 服务,可以用来允许客户端组件直接与开关交互。这样的提供者在应用程序内部、测试期间和调试期间可能很有用。该提供者将用于将消息直接注入开关,并以与内部组件相同的方式根据订阅接收消息。如果需要将现有组件移出应用程序的主应用程序域,则实现开关接口的提供者可以替代实际的开关注入。
性能
开关与提供者模式的目标之一是提供最佳性能。提供者应以最佳方式从传入数据创建消息,其实现的质量将决定它们对性能的影响。开关通过引用传递消息,因此不会引入任何复制操作开销。由于规则测试过程,开关在发送消息时引入的开销最小。与匹配复杂测试的一组单规则订阅相比,使用正确选择的规则链可以指数级地减少选择订阅者的开销。
在规则链经过仔细选择的情况下,复杂度将接近 O(log n),其中 n 是节点总数;在最坏的情况下,通过开关传递消息的复杂度为 O(n)。订阅和取消订阅操作具有相似的复杂度。
对性能敏感的组件可以选择使用专用于其目的的开关实例。
可维护性
开关与提供者模式促进了软件系统中组件的解耦,并提高了修改和替换组件的能力,而无需进行大规模重构。可以向系统中插入额外的组件,并且生成未使用消息的组件可能不需要处理这些消息。
结合依赖注入,开关实例和提供者实例可以动态配置,以匹配应用程序行为和性能要求,并有助于提高测试灵活性。
测试自动化
在测试期间使用的潜力是采用开关与提供者架构的有用好处之一。可以向开关添加一个订阅,该订阅将消息在传入时序列化到文件中,以便以后可以通过读取文件并传递消息的自定义提供者进行重放。在测试应用程序中使用开关与提供者的功能,提供了一种方便的方法来执行代码,否则这些代码在不向应用程序添加自定义代码以支持测试的情况下将很难激活。
使用开关与提供者模式的测试场景示例是,用脚本提供者替换驱动程序(该驱动程序通过开关发送包含传入数据的消息),脚本提供者发送各种消息组合,用于理想情况和故障情况,而这些情况用普通驱动程序很难重现。
历史
- 2009-06-01 - 初始文章版本。
- 2009-07-27 - 更新以供发布。
- 2009-07-28 - 添加 ExampleApp 项目以说明模式用法。