c++ - 如何在 C++ 中透明地处理不同的协议(protocol)版本?

标签 c++ language-agnostic design-patterns protocols

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

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

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

执行此操作的天真方法是在代码中乱加这样的语句:

if (clientProtocolVersion == 1)
    // do something here
else if (clientProtocolVersion == 2)
    // do something else here
else if (clientProtocolVersion == 3)
    // do a third thing here...

这个解决方案很差,原因如下:

  1. 当我添加新的协议(protocol)版本时,我必须在源代码树中的所有地方找到使用这些 if 语句的地方,并修改它们以添加新功能。
  2. 如果出现新的协议(protocol)版本,并且协议(protocol)版本的某些部分与另一个版本相同,我需要修改 if 语句,使其变为 if (clientProtoVersion == 5 || clientProtoVersion == 6 )
  3. 我敢肯定还有更多原因会导致它的设计糟糕,但我现在想不出它们。

我正在寻找的是一种使用 C++ 语言的特性智能地处理不同协议(protocol)的方法。我考虑过使用模板类,可能使用指定协议(protocol)版本的模板参数,或者可能是类层次结构,每个不同的协议(protocol)版本一个类......

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

编辑:

你们中的许多人都建议继承层次结构,最旧的协议(protocol)版本在顶部,就像这样(请原谅我的 ASCII 艺术):

IProtocol
    ^
    |
CProtoVersion1
    ^
    |
CProtoVersion2
    ^
    |
CProtoVersion3

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

  • 将默认实现设为 NO_OP(或者可能在某处记录消息)。
  • 抛出一个异常,尽管这似乎是个坏主意,即使我正在输入它也是如此。
  • ...做点别的吗?

编辑2:

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

在协议(protocol)版本 1 中,我可能有:

ByteArray getFooMessage(string param1, int param2)

在协议(protocol)版本 2 中我可能想要:

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

这两个不同的协议(protocol)版本现在有不同的方法签名,这很好,除了它迫使我检查所有调用代码并将所有具有 2 个参数的调用更改为 3 个参数,具体取决于所使用的协议(protocol)版本,即我首先要避免的是什么!

将协议(protocol)版本信息与其余代码分开的最佳方法是什么,以便对您隐藏当前协议(protocol)的细节?

最佳答案

由于您需要动态选择要使用的协议(protocol),使用不同的类(而不是模板参数)来选择协议(protocol)版本似乎是正确的方法。从本质上讲,这是一种策略模式,但如果您想更详细地说明,也可以使用访问者模式。

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

无论您决定如何组织层次结构,您都希望在知道协议(protocol)版本后立即选择协议(protocol)版本对象,然后将其传递给需要“讨论”协议(protocol)的各种事物。

关于c++ - 如何在 C++ 中透明地处理不同的协议(protocol)版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1493524/

相关文章:

c++ - 排序、唯一、删除不起作用

c++ - 多态命令解析器设计

language-agnostic - 什么是最简洁的编程语言?

algorithm - 确定 DAG 是否具有从所有其他顶点可达的顶点的线性时间算法?

Java 二叉树/访问者模式

c++ - 如何在 C++ 中实现观察者模式

c++ - std::list 排序算法运行时

c++ - 类似于 glib 的对象模型?

swift - Swift 中的计算只读属性与函数

c# - 分层但不整齐的系统的类设计