шаблоны проектирования c ++ для объединения преобразований потоков объектов - PullRequest
4 голосов
/ 15 декабря 2011

Я работаю над многопоточной библиотекой, которая отслеживает сетевой трафик из winpcap и преобразует пакеты в несколько различных типов структур данных для использования различными приложениями.

для каждого типа выходных данных потребуется несколько преобразований, каждое преобразование можно описать как получение 0-N объектов типа X, а затем создание 0-N типов Y, которые затем будут использованы следующим шагом в процесс.

Важно отметить, что при преобразовании X в Y. Если в настоящее время у нас есть только 5 (в качестве примера) X, этого может быть или не быть достаточно для создания Y, или может быть достаточно для создания многих Y, в зависимости от преобразования и полученных данных.

Чтобы быть последовательными, мы, очевидно, хотели бы использовать стандартный шаблон для каждого объекта преобразования. Я надеюсь, что кто-то может указать на обычно используемый шаблон для чего-то подобного, который, как мы надеемся, опирается на библиотеки std (или boost).

Кроме того, мы обсуждали возможность использования цепочек наследования для объединения различных слоев.

IE.

class ProcessXtoY: ProcessWtoX
{
    void processData(iterator<X> begin, iterator<X> end)
    {
        /* create Y's, send output to  */
    }
    virtual void processData(iterator<Y> begin, iterator<Y> end) = 0;
}

class ProcessYtoZ: ProcessXtoY
{
    void processData(iterator<Y> begin, iterator<Y> end)
    {
        /* ... */
    }
}

Кто-нибудь может предложить несколько примеров часто используемых шаблонов для этого типа проекта?

Ответы [ 3 ]

2 голосов
/ 15 декабря 2011

Использование наследования для связывания преобразований - это не то, для чего следует использовать наследование, и оно довольно негибко при добавлении новых преобразований. Если вам когда-нибудь понадобятся новые комбинации преобразований (например, W непосредственно в Y).

Вместо этого вы рассматривали создание класса (ов) преобразования, которые описывают каждый алгоритм преобразования, а затем использовали std :: transform и объединяли преобразования в цепочку?

1 голос
/ 15 декабря 2011

У меня есть несколько предложений. Вы можете использовать вариант Pattern Decorator . Вы можете изменить этот шаблон, чтобы объединить различные типы объектов. Тогда, если у вас есть разные реализации одного и того же преобразования, это легко проблематично или во время выполнения вытеснить. Возможно, где-то уже есть шаблон с таким именем, но вы должны быть в состоянии извлечь его из основ шаблона Decorator.

Если вам нужно многопоточное решение, я бы порекомендовал объединить ваши преобразования в очередь производителя / потребителя (см. this ). Таким образом, вы можете параллельно работать с несколькими различными потребителями (преобразованиями) и размещать завершенные преобразования на следующем производителе / ​​потребителе в очереди. Конечно, это действительно работает только тогда, когда порядок ваших преобразований не имеет значения для остальной части вашей программы, или у вас есть какой-то способ отследить это и изменить порядок конечных объектов, когда они снова понадобятся. Опять же, вы можете легко заменять свои преобразования программно или во время выполнения, если у вас есть разные их реализации.

Если вам нужно что-то более общее и настраиваемое, вы можете использовать Pattern Builder , чтобы инкапсулировать процесс связывания и обеспечить полную конфигурацию во время выполнения построителя и иметь более точное управление выгрузкой процесса связывания. Конечно, вы должны использовать другие шаблоны в компоновщике для реализации цепочек преобразований.

1 голос
/ 15 декабря 2011

Подход в вашем примере (я бы назвал это «итеративным» подходом) является очевидным неуклюжим - вы проталкиваете бесконечный поток пакетов, поэтому для них нет конца ().

Я думаю, что вы можете пойти с натяжением или толчком подходов.Для тяги, что-то в Java имеет hasNext () / next ().К сожалению, его сложно разветвить, и исходный источник данных должен стоять в очереди, потому что мы не знаем, когда потребители возьмут в карман.

Для подхода push вы можете использовать register (listener) и listener.process () сочетаниеОн легко разветвляется, и система может выполнять буферизацию (в случае, если process () на уровне сетевых пакетов занимает слишком много времени), или вы можете вводить явные очереди на любом уровне.

Таким образом, в целомЯ бы порекомендовал слушателей событий здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...