这是一个通用的 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...
这个解决方案很差,原因如下:
- 当我添加新的协议(protocol)版本时,我必须在源代码树中的所有地方找到使用这些 if 语句的地方,并修改它们以添加新功能。
- 如果出现新的协议(protocol)版本,并且协议(protocol)版本的某些部分与另一个版本相同,我需要修改 if 语句,使其变为
if (clientProtoVersion == 5 || clientProtoVersion == 6 )
。 - 我敢肯定还有更多原因会导致它的设计糟糕,但我现在想不出它们。
我正在寻找的是一种使用 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/