這是一個通用的C++設計問題。如何在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...
該解決方案是相當差,有以下原因:
- 當我添加新的協議版本,我必須在源碼樹中的任何地方找到這些if語句,並修改它們以添加新功能。
- 如果出現一個新的協議版本,並且協議版本的某些部分與另一個版本相同,我需要修改if語句,以便他們讀取
if (clientProtoVersion == 5 || clientProtoVersion == 6)
。 - 我相信有更多的原因是它的設計不好,但現在我想不起來。
我在尋找的是一種使用C++語言的特性智能處理不同協議的方法。我想過用模板類,可能與模板參數指定的協議版本,或者一個類層次結構,對於每一個不同的協議版本一類...
我敢肯定,這是一個很常見的設計模式,很多很多人以前一定有過這個問題。
編輯:
你們中許多人認爲繼承層次結構,在頂部的最古老的協議版本,像這樣的(請原諒我的ASCII藝術):
IProtocol
^
|
CProtoVersion1
^
|
CProtoVersion2
^
|
CProtoVersion3
...就resuse而言,這似乎是一個明智的做法。但是,當您需要擴展協議並添加基本上新的消息類型時會發生什麼?如果我在IProtocol
中添加虛擬方法,並在CProtocolVersion4
中實現這些新方法,那麼在早期協議版本中如何處理這些新方法?我想我的選擇是:
- 使默認實現NO_OP(或可能在某處記錄消息)。
- 拋出一個異常,雖然這似乎是一個壞主意,即使我輸入它。
- ...做別的事嗎?
EDIT2:
而且上述問題,會發生什麼,當一個新的協議消息需要比舊版本更多的投入?例如:
在通訊協定第1版,我可能有:
ByteArray getFooMessage(string param1, int param2)
而且在協議版本2我可能想:
ByteArray getFooMessage(string param1, int param2, float param3)
兩個不同的協議版本現在有不同的方法簽名,這很好,除了它迫使我通過所有調用代碼並將所有調用改爲2個參數爲3個參數,具體取決於正在使用的協議版本,我這是我試圖避免的第一個地方!
從其他代碼中分離協議版本信息的最佳方式是什麼,以便當前協議的細節對您是隱藏的?
實際上,策略模式是最有可能的方法,您可能希望與Factory合併,該工廠將負責爲您使用的版本提供正確的「策略」。 – 2009-09-29 16:23:33