如何在c ++中透明地处理不同的协议版本?

Tho*_*omi 7 c++ language-agnostic design-patterns protocols

这是一个通用的C++设计问题.

我正在编写一个使用客户端/服务器模型的应用程序.现在我正在编写服务器端.许多客户已经存在(一些由我自己编写,另一些由第三方编写).问题是这些现有客户端都使用不同的协议版本(多年来已经有2-3次协议更改).

由于我正在重写服务器,我认为现在是设计我的代码的好时机,这样我就可以透明地处理许多不同的协议版本.在所有协议版本中,来自客户端的第一个通信包含协议版本,因此对于每个客户端连接,服务器确切地知道它需要谈论哪个协议.

执行此操作的天真方法是使用以下语句来丢弃代码:

if (clientProtocolVersion == 1)
    // do something here
else if (clientProtocolVersion == 2)
    // do something else here
else if (clientProtocolVersion == 3)
    // do a third thing here...
Run Code Online (Sandbox Code Playgroud)

由于以下原因,此解决方案非常糟糕:

  1. 当我添加新协议版本时,我必须在源树中找到使用这些if语句的所有位置,并修改它们以添加新功能.
  2. 如果出现了新的协议版本,并且协议版本的某些部分与另一个版本相同,我需要修改if语句以便它们读取if (clientProtoVersion == 5 || clientProtoVersion == 6).
  3. 我确信有更多的理由说明它的设计不好,但我现在想不到它们.

我正在寻找的是一种使用C++语言的功能智能地处理不同协议的方法.我考虑过使用模板类,可能使用指定协议版本的模板参数,或者可能是类heirarchy,每个不同的协议版本都有一个类...

我敢肯定这是一种非常常见的设计模式,所以很多人以前都遇到过这个问题.

编辑:

你们中的许多人已经建议继承heirarchy,最旧的协议版本在顶部,像这样(请原谅我的ASCII艺术):

IProtocol
    ^
    |
CProtoVersion1
    ^
    |
CProtoVersion2
    ^
    |
CProtoVersion3
Run Code Online (Sandbox Code Playgroud)

......就重复使用而言,这似乎是一件明智的事情.但是,当您需要扩展协议并添加基本的新消息类型时会发生什么?如果我在其中添加虚拟方法IProtocol并实现这些新方法CProtocolVersion4,那么在早期协议版本中如何处理这些新方法?我想我的选择是:

  • 使默认实现为NO_OP(或者可能在某处记录消息).
  • 抛出一个例外,虽然这似乎是一个坏主意,即使我正在输入它.
  • ......做点别的吗?

EDIT2:

除了上述问题,当较新的协议消息需要比旧版本更多的输入时会发生什么?例如:

在protocl版本1中,我可能有:

ByteArray getFooMessage(string param1, int param2)

在协议版本2中,我可能想要:

ByteArray getFooMessage(string param1, int param2, float param3)

两个不同的协议版本现在有不同的方法签名,这很好,除了它迫使我通过所有调用代码并将所有调用更改为2个参数到3个参数,具体取决于所使用的协议版本,这就是我所说的我试图避免在第一位!

将协议版本信息与其余代码分离的最佳方法是什么,以便隐藏当前协议的具体内容?

Lau*_*ves 10

由于您需要动态选择要使用的协议,因此使用不同的类(而不是模板参数)来选择协议版本似乎是正确的方法.基本上这是战略模式,虽然如果你想要真正详细,访客也是可能的.

由于这些都是同一协议的不同版本,因此您可能在基类中有共同的东西,然后是子类的差异.另一种方法可能是使基类用于最旧版本的协议,然后让每个后续版本都具有继承自先前版本的类.这是一个有点不寻常的继承树,但它的好处是它保证为更高版本所做的更改不会影响旧版本.(我假设旧协议版本的类会很快稳定下来,然后很少会改变.

但是,如果您决定组织层次结构,则需要在知道协议版本后立即选择协议版本对象,然后将其传递给需要"协商"协议的各种事物.

  • 事实上,策略模式是最可能的方法,您可能希望与Factory结合使用,它将负责为您使用的版本提供正确的"策略". (2认同)