2013-12-15 3 views
0

Рассмотрите пакет, откуда-то откуда-то. Он имеет поле VERSION, существует N возможных ВЕРСИЙ входящего пакета. Каждого пакет с VERSION X должен быть обработан с помощью соответствующих методов/набора инструкций для каждого пакет ВЕРСИИ от X до 1. Моей единственной идеи, чтобы выполнить эту задачу очень некрасиво, как:Обработка обработки входящих пакетов - вопросы проектирования

PACKET p = GetPacketFromSomewhere(); 
// p.VERSION is 3 

if (p.VERSION > 0) { 
    // things for p.VERSION == 1 
} 

if (p.VERSION > 1) { 
    // things for p.VERSION == 2 
} 

if (p.VERSION > 2) { 
    // things for p.VERSION == 3 
} 

// set of if statements up to version N 

Реальная ситуация такова, что , У меня есть пакет VERSIONS выше номера 10, и все еще может измениться. Новые пакеты VERSIONS будут добавлены, в то время как мне нужно сохранить обратную совместимость. Этот код плох, по крайней мере мне это не нравится. Вы, ребята, лучше знаете, как справиться с этим делом?

ответ

2

Используйте map типа map<unsigned int, function> где function является указателем на функцию требуемого типа:

typedef void (*function)(); 
std::map<int,function> handlers; 
handlers[1] = &ver1handler; 
... 
handlers[N] = &verNhandler; 

if(handlers.count(p.VERSION)) 
    (*handlers.find(p.VERSION))(); 

где ver[N+1]handler будет определяться как:

void ver[N+1]handler(){ 
    ver[N]handler(); 
    // additional handle commands 
} 

Или используйте команду switch, с обработчиками, определенными таким же образом.

+0

Ваше решение было бы уместным, если бы OP захотел выполнить один блок для любого номера версии. Похоже, он/она хочет выполнить каждый блок * до * данного номера; например для 'VERSION == 3', он должен выполнить блоки 0, 1 и 2. –

+0

Спасибо. Не заметил. Изменен пост :) –

+0

Я не думаю, что есть необходимость в std: map here. Простой вектор - с протокольной версией, имеющей индекс функций - должен быть достаточным. – MikeMB

2

Если порядок обработки не имеет значения, вы можете использовать переключатель без перерыва:

PACKET p = GetPacketFromSomewhere(); 
// p.VERSION is 3 

switch (p.VERSION) { 
    case 3: { 
     // things for p.VERSION == 3 
    } 
    case 2: { 
     // things for p.VERSION == 2 
    } 
    case 1: { 
     // things for p.VERSION == 1 
    } 
} 

EDIT: Можно также использовать рекурсивный шаблон функции специализации, как это:

template<int N> 
void proc(PACKET& p){ 
    proc<N-1>(p);   
} 

template<> 
void proc<1>(PACKET& p){ 
    //things for p.VERSION == 1 
} 

template<> 
void proc<2>(PACKET& p){ 
    proc<1>(p) 
    //things for p.VERSION == 2 
} 

template<> 
void proc<3>(PACKET& p){ 
    proc<2>(p) 
    //things for p.VERSION == 3 
} 

, а затем вызовите функцию обработки следующим образом:

switch (p.VERSION) { 
    case 1: proc<1>(p) break; 
    case 3: proc<2>(p) break; 
    case 3: proc<3>(p) break; 
    default: { 
     std::cout << "Protocol version not impplemented - using highest known version" << std::endl; 
     proc<3>(p); 
} 

Это также должно быть довольно эффективная производительность (в случае, если это вас беспокоит), и вам не нужно беспокоиться о пробелах в версии протокола.

+0

Я предполагаю, что сам компилятор заказывает дела, и я вижу только случай 1: выполнен. Есть мой тестовый код http://pastebin.com/iDBVPkvh – igleyy

+0

К сожалению, это была опечатка. Я исправил условие в инструкции switch. – MikeMB

+0

Что касается вашего предыдущего вопроса: я бы просто придерживался вашего оригинального решения, если вам нужно использовать функции обработки в порядке возрастания. Если вам нужно перемежать функции из более высоких версий протокола между более низкими, вы должны использовать рекурсивное определение. – MikeMB

Смежные вопросы